32 #include <sys/types.h>
38 #include <arpa/inet.h>
47 #define IAX_FIRMWARE_SUBDIR "/firmware/iax"
60 static int try_firmware(
char *s)
64 int ifd, fd, res, len, chunk;
67 unsigned char sum[16], buf[1024];
72 last = strrchr(s,
'/');
78 snprintf(s2, strlen(s) + 100,
"/var/tmp/%s-%ld", last, ast_random());
80 if (stat(s, &stbuf) < 0) {
81 ast_log(LOG_WARNING,
"Failed to stat '%s': %s\n", s, strerror(errno));
86 if (S_ISDIR(stbuf.st_mode))
88 ifd = open(s, O_RDONLY);
90 ast_log(LOG_WARNING,
"Cannot open '%s': %s\n", s, strerror(errno));
93 fd = open(s2, O_RDWR | O_CREAT | O_EXCL, AST_FILE_MODE);
95 ast_log(LOG_WARNING,
"Cannot open '%s' for writing: %s\n", s2, strerror(errno));
106 if (chunk >
sizeof(buf))
108 res = read(ifd, buf, chunk);
110 ast_log(LOG_WARNING,
"Only read %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
115 res = write(fd, buf, chunk);
117 ast_log(LOG_WARNING,
"Only write %d of %d bytes of data :(: %s\n", res, chunk, strerror(errno));
126 lseek(fd, 0, SEEK_SET);
127 if ((res = read(fd, &fwh2,
sizeof(fwh2))) !=
sizeof(fwh2)) {
128 ast_log(LOG_WARNING,
"Unable to read firmware header in '%s'\n", s);
132 if (ntohl(fwh2.
magic) != IAX_FIRMWARE_MAGIC) {
133 ast_log(LOG_WARNING,
"'%s' is not a valid firmware file\n", s);
137 if (ntohl(fwh2.
datalen) != (stbuf.st_size -
sizeof(fwh2))) {
138 ast_log(LOG_WARNING,
"Invalid data length in firmware '%s'\n", s);
143 ast_log(LOG_WARNING,
"No or invalid device type specified for '%s'\n", s);
148 if (fwh == MAP_FAILED) {
149 ast_log(LOG_WARNING,
"mmap failed: %s\n", strerror(errno));
154 MD5Update(&md5, fwh->data, ntohl(fwh->
datalen));
156 if (memcmp(sum, fwh->
chksum,
sizeof(sum))) {
157 ast_log(LOG_WARNING,
"Firmware file '%s' fails checksum\n", s);
158 munmap((
void*)fwh, stbuf.st_size);
164 if (!strcmp((
const char *) cur->fwh->
devname, (
const char *) fwh->
devname)) {
166 if (cur->dead || (ntohs(cur->fwh->
version) < ntohs(fwh->
version)))
171 munmap((
void*)fwh, stbuf.st_size);
177 if (!cur && ((cur =
ast_calloc(1,
sizeof(*cur))))) {
184 munmap((
void*)cur->fwh, cur->mmaplen);
189 cur->mmaplen = stbuf.st_size;
200 munmap((
void*)cur->fwh, ntohl(cur->fwh->
datalen) +
sizeof(*(cur->fwh)));
206 void iax_firmware_reload(
void)
211 char fn[PATH_MAX +
sizeof(IAX_FIRMWARE_SUBDIR) +
sizeof(de->d_name)];
221 snprintf(fn,
sizeof(fn),
"%s%s", ast_config_AST_DATA_DIR, IAX_FIRMWARE_SUBDIR);
224 while((de = readdir(fwd))) {
225 if (de->d_name[0] !=
'.') {
226 snprintf(fn,
sizeof(fn),
"%s%s/%s",
227 ast_config_AST_DATA_DIR, IAX_FIRMWARE_SUBDIR, de->d_name);
228 if (!try_firmware(fn)) {
229 ast_verb(2,
"Loaded firmware '%s'\n", de->d_name);
235 ast_log(LOG_WARNING,
"Error opening firmware directory '%s': %s\n", fn, strerror(errno));
243 destroy_firmware(cur);
250 void iax_firmware_unload(
void)
257 destroy_firmware(cur);
263 int iax_firmware_get_version(
const char *dev, uint16_t *version)
267 if (ast_strlen_zero(dev))
272 if (!strcmp(dev, (
const char *) cur->fwh->
devname)) {
273 *version = ntohs(cur->fwh->
version);
283 int iax_firmware_append(
struct iax_ie_data *ied,
const char *dev,
unsigned int desc)
286 unsigned int bs = desc & 0xff;
287 unsigned int start = (desc >> 8) & 0xffffff;
291 if (ast_strlen_zero((
char *)dev) || !bs)
298 if (strcmp(dev, (
const char *) cur->fwh->
devname))
301 if (start < ntohl(cur->fwh->
datalen)) {
302 bytes = ntohl(cur->fwh->
datalen) - start;
321 void iax_firmware_traverse(
334 if (!filter || !strcasecmp(filter, (
const char *) cur->fwh->
devname)) {
335 if (callback(cur->fwh, data)) {
#define AST_LIST_LOCK(head)
Locks a list.
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Asterisk file paths, configured in asterisk.conf.
IAX Firmware Support header file.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
A set of macros to manage forward-linked lists.
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define IAX_IE_FWBLOCKDESC
#define ast_calloc(num, len)
A wrapper for calloc()
#define IAX_IE_FWBLOCKDATA
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
static int filter(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)