// This IPv6 address parser handles any valid textual representation according to RFC-4291 and RFC-5952. // Other representations will return -1. // // note that str input parameter has been modified when the function call returns // // parse_ipv6(char *str, struct in6_addr *retaddr) // parse textual representation of IPv6 addresses // str: input arg // retaddr: output arg int parse_ipv6(char *str, struct in6_addr *retaddr) { bool compressed_field_found = false; unsigned char *_retaddr = (unsigned char *) retaddr; char *_str = str; char *delim; bzero((void *) retaddr, sizeof(struct in6_addr)); if (!strlen(str) || strchr(str, ':') == NULL || (str[0] == ':' && str[1] != ':') || (strlen(str) >= 2 && str[strlen(str) - 1] == ':' && str[strlen(str) - 2] != ':')) return -1; // convert transitional to standard textual representation if (strchr(str, '.')) { int ipv4bytes[4]; char *curp = strrchr(str, ':'); if (curp == NULL) return -1; char *_curp = ++curp; for (int i = 0; i < 4; i++) { char *nextsep = strchr(_curp, '.'); if (_curp[0] == '0' || (i < 3 && nextsep == NULL) || (i == 3 && nextsep != NULL)) return -1; if (nextsep != NULL) *nextsep = 0; for (int j = 0; j < strlen(_curp); j++) if (_curp[j] < '0' || _curp[j] > '9') return -1; if (strlen(_curp) > 3) return -1; const long val = strtol(_curp, NULL, 10); if (val < 0 || val > 255) return -1; ipv4bytes[i] = val; _curp = nextsep + 1; } sprintf(curp, "%x%02x:%x%02x", ipv4bytes[0], ipv4bytes[1], ipv4bytes[2], ipv4bytes[3]); } // parse standard textual representation do { if ((delim = strchr(_str, ':')) == _str || (delim == NULL && !strlen(_str))) { if (delim == str) _str++; else if (delim == NULL) return 0; else { if (compressed_field_found == true) return -1; if (delim == str + strlen(str) - 1 && _retaddr != (unsigned char *) (retaddr + 1)) return 0; compressed_field_found = true; _str++; int cnt = 0; for (char *__str = _str; *__str; ) if (*(__str++) == ':') cnt++; unsigned char *__retaddr = - 2 * ++cnt + (unsigned char *) (retaddr + 1); if (__retaddr <= _retaddr) return -1; _retaddr = __retaddr; } } else { char hexnum[4] = "0000"; if (delim == NULL) delim = str + strlen(str); if (delim - _str > 4) return -1; for (int i = 0; i < delim - _str; i++) if (!isxdigit(_str[i])) return -1; else hexnum[4 - (delim - _str) + i] = tolower(_str[i]); _str = delim + 1; *(_retaddr++) = (digit2int(hexnum[0]) << 4) + digit2int(hexnum[1]); *(_retaddr++) = (digit2int(hexnum[2]) << 4) + digit2int(hexnum[3]); } } while (_str < str + strlen(str)); return 0; }
// This Ethernet address parser only handles the hexadecimal representation made of 6 groups of 2 hexadecimal // numbers separated by colons: "XX:XX:XX:XX:XX:XX". // Other representations will return -1. int parse_mac(char *str, struct ether_addr *retaddr) { if (strlen(str) != MACMAXSIZE) return -1; for (int i = 0; i < 6; i++) { if ((i < 5 && str[3 * i + 2] != ':') || !isxdigit(str[3 * i]) || !isxdigit(str[3 * i + 1])) return -1; retaddr->octet[i] = (digit2int(tolower(str[3 * i])) << 4) + digit2int(tolower(str[3 * i + 1])); } return 0; }
static unsigned int fourhex2int(lua_State *L, const char *code) { unsigned int utf = 0; utf += digit2int(L, code[0]) * 4096; utf += digit2int(L, code[1]) * 256; utf += digit2int(L, code[2]) * 16; utf += digit2int(L, code[3]); return utf; }
void getnum_aux(GetCharFunction getf, int x, int* iout, char* cout) { char c = getf(); if (isdigit(c)) { getnum_aux(getf, x*10 + digit2int(c), iout, cout); } else { *iout = x; *cout = c; } }
// Given a function to get the next character in an input stream, // return the next integer in the input stream and following character. // If there is not an integer at the front of the stream, returns false // and the integer value is not updated. bool getnum(GetCharFunction getf, int* iout, char* cout) { char c = getf(); if (isdigit(c)) { getnum_aux(getf, digit2int(c), iout, cout); return true; } else { *cout = c; return false; } }
static int hex2int(char *s) { int res; int tmp; /* Gotta be at least one digit */ if (strlen(s) < 1) return -1; /* Can't be more than two */ if (strlen(s) > 2) return -1; /* Grab the first digit */ res = digit2int(s[0]); if (res < 0) return -1; tmp = res; /* Grab the next */ if (strlen(s) > 1) { res = digit2int(s[1]); if (res < 0) return -1; tmp = tmp * 16 + res; } return tmp; }
static unsigned long long read_num(const char *s, int base, const char *name) { const char *p = s; unsigned long long i = 0; while (*p != '\0' && isxdigit(*p)) { i *= base; i += (unsigned) digit2int(*p); ++p; } if (*p != '\0') errx(1, "%s: not a %s number", s, name ? name : "valid"); return i; }
static void *ztdlocal_create(struct dahdi_span *span, char *address) { struct ztdlocal *z, *l; unsigned long flags; int key = -1, id = -1, monitor = -1; if (strlen(address) >= 3) { if (address[1] != ':') goto INVALID_ADDRESS; key = digit2int(address[0]); id = digit2int(address[2]); } if (strlen (address) == 5) { if (address[3] != ':') goto INVALID_ADDRESS; monitor = digit2int(address[4]); } if (key == -1 || id == -1) goto INVALID_ADDRESS; z = kmalloc(sizeof(struct ztdlocal), GFP_KERNEL); if (z) { /* Zero it out */ memset(z, 0, sizeof(struct ztdlocal)); z->key = key; z->id = id; z->span = span; spin_lock_irqsave(&zlock, flags); /* Add this peer to any existing spans with same key And add them as peers to this one */ for (l = zdevs; l; l = l->next) if (l->key == z->key) { if (l->id == z->id) { printk(KERN_DEBUG "TDMoL: Duplicate id (%d) for key %d\n", z->id, z->key); goto CLEAR_AND_DEL_FROM_PEERS; } if (monitor == -1) { if (l->peer) { printk(KERN_DEBUG "TDMoL: Span with key %d and id %d already has a R/W peer\n", z->key, z->id); goto CLEAR_AND_DEL_FROM_PEERS; } else { l->peer = z; z->peer = l; } } if (monitor == l->id) { if (l->monitor_rx_peer) { printk(KERN_DEBUG "TDMoL: Span with key %d and id %d already has a monitoring peer\n", z->key, z->id); goto CLEAR_AND_DEL_FROM_PEERS; } else { l->monitor_rx_peer = z; } } } z->next = zdevs; zdevs = z; spin_unlock_irqrestore(&zlock, flags); if(!try_module_get(THIS_MODULE)) printk(KERN_DEBUG "TDMoL: Unable to increment module use count\n"); printk(KERN_INFO "TDMoL: Added new interface for %s, key %d id %d\n", span->name, z->key, z->id); } return z; CLEAR_AND_DEL_FROM_PEERS: for (l = zdevs; l; l = l->next) { if (l->peer == z) l->peer = NULL; if (l->monitor_rx_peer == z) l->monitor_rx_peer = NULL; } kfree (z); spin_unlock_irqrestore(&zlock, flags); return NULL; INVALID_ADDRESS: printk (KERN_NOTICE "TDMoL: Invalid address %s\n", address); return NULL; }