int osip_message_set_multiple_header(osip_message_t * sip, char *hname, char *hvalue) { int i; char *ptr; /* current location of the search */ char *comma; /* This is the separator we are elooking for */ char *beg; /* beg of a header */ char *end; /* end of a header */ char *quote1; /* first quote of a pair of quotes */ char *quote2; /* second quuote of a pair of quotes */ size_t hname_len; /* Find header based upon lowercase comparison */ osip_tolower(hname); if (hvalue == NULL) { i = osip_message_set__header(sip, hname, hvalue); if (i != 0) return i; return OSIP_SUCCESS; } ptr = hvalue; comma = strchr(ptr, ','); hname_len = strlen(hname); if (comma == NULL || (hname_len == 4 && strncmp(hname, "date", 4) == 0) || (hname_len == 2 && strncmp(hname, "to", 2) == 0) || (hname_len == 4 && strncmp(hname, "from", 4) == 0) || (hname_len == 7 && strncmp(hname, "call-id", 7) == 0) || (hname_len == 4 && strncmp(hname, "cseq", 4) == 0) || (hname_len == 7 && strncmp(hname, "subject", 7) == 0) || (hname_len == 7 && strncmp(hname, "expires", 7) == 0) || (hname_len == 6 && strncmp(hname, "server", 6) == 0) || (hname_len == 10 && strncmp(hname, "user-agent", 10) == 0) || (hname_len == 16 && strncmp(hname, "www-authenticate", 16) == 0) || (hname_len == 19 && strncmp(hname, "authentication-info", 19) == 0) || (hname_len == 18 && strncmp(hname, "proxy-authenticate", 18) == 0) || (hname_len == 19 && strncmp(hname, "proxy-authorization", 19) == 0) || (hname_len == 25 && strncmp(hname, "proxy-authentication-info", 25) == 0) || (hname_len == 12 && strncmp(hname, "organization", 12) == 0) || (hname_len == 13 && strncmp(hname, "authorization", 13) == 0)) /* there is no multiple header! likely */ /* to happen most of the time... */ /* or hname is a TEXT-UTF8-TRIM and may */ /* contain a comma. this is not a separator */ /* THIS DOES NOT WORK FOR UNKNOWN HEADER!!!! */ { i = osip_message_set__header(sip, hname, hvalue); if (i != 0) return i; return OSIP_SUCCESS; } beg = hvalue; end = NULL; quote2 = NULL; while (comma != NULL) { quote1 = __osip_quote_find(ptr); if (quote1 != NULL) { quote2 = __osip_quote_find(quote1 + 1); if (quote2 == NULL) return OSIP_SYNTAXERROR; /* quotes comes by pair */ ptr = quote2 + 1; } if ((quote1 == NULL) || (quote1 > comma)) { /* We must search for the next comma which is not within quotes! */ end = comma; if (quote1 != NULL && quote1 > comma) { /* comma may be within the quotes */ /* ,<sip:[email protected]>;methods=\"INVITE,BYE,OPTIONS,ACK,CANCEL\",<sip:[email protected]> */ /* we want the next comma after the quotes */ char *tmp_comma; char *tmp_quote1; char *tmp_quote2; tmp_quote1 = quote1; tmp_quote2 = quote2; tmp_comma = strchr(comma + 1, ','); while (1) { if (tmp_comma < tmp_quote1) break; /* ok (before to quotes) */ if (tmp_comma < tmp_quote2) { tmp_comma = strchr(tmp_quote2 + 1, ','); } tmp_quote1 = __osip_quote_find(tmp_quote2 + 1); if (tmp_quote1 == NULL) break; tmp_quote2 = __osip_quote_find(tmp_quote1 + 1); if (tmp_quote2 == NULL) break; /* probably a malformed message? */ } comma = tmp_comma; /* this one is not enclosed within quotes */ } else comma = strchr(comma + 1, ','); if (comma != NULL) ptr = comma + 1; } else if ((quote1 < comma) && (quote2 < comma)) { /* quotes are located before the comma, */ /* continue the search for next quotes */ ptr = quote2 + 1; } else if ((quote1 < comma) && (comma < quote2)) { /* if comma is inside the quotes... */ /* continue with the next comma. */ ptr = quote2 + 1; comma = strchr(ptr, ','); if (comma == NULL) /* this header last at the end of the line! */ { /* this one does not need an allocation... */ #if 0 if (strlen(beg) < 2) return OSIP_SUCCESS; /* empty header */ #else if (beg[0] == '\0' || beg[1] == '\0') return OSIP_SUCCESS; /* empty header */ #endif osip_clrspace(beg); i = osip_message_set__header(sip, hname, beg); if (i != 0) return i; return OSIP_SUCCESS; } } if (end != NULL) { char *avalue; if (end - beg + 1 < 2) return OSIP_SYNTAXERROR; avalue = (char *) osip_malloc(end - beg + 1); if (avalue == NULL) return OSIP_NOMEM; osip_clrncpy(avalue, beg, end - beg); /* really store the header in the sip structure */ i = osip_message_set__header(sip, hname, avalue); osip_free(avalue); if (i != 0) return i; beg = end + 1; end = NULL; if (comma == NULL) /* this header last at the end of the line! */ { /* this one does not need an allocation... */ #if 0 if (strlen(beg) < 2) return OSIP_SUCCESS; /* empty header */ #else if (beg[0] == '\0' || beg[1] == '\0') return OSIP_SUCCESS; /* empty header */ #endif osip_clrspace(beg); i = osip_message_set__header(sip, hname, beg); if (i != 0) return i; return OSIP_SUCCESS; } } } return OSIP_SYNTAXERROR; /* if comma is NULL, we should have already return 0 */ }
int osip_message_set_multiple_header (osip_message_t * sip, char *hname, char *hvalue) { int i; char *ptr, *p; /* current location of the search */ char *comma; /* This is the separator we are elooking for */ char *beg; /* beg of a header */ char *end; /* end of a header */ int inquotes, inuri; /* state for inside/outside of double-qoutes or URI */ size_t hname_len; /* Find header based upon lowercase comparison */ osip_tolower (hname); if (hvalue == NULL) { i = osip_message_set__header (sip, hname, hvalue); if (i != 0) return i; return OSIP_SUCCESS; } ptr = hvalue; comma = strchr (ptr, ','); hname_len = strlen (hname); if (comma == NULL || (hname_len == 4 && strncmp (hname, "date", 4) == 0) || (hname_len == 1 && strncmp (hname, "t", 1) == 0) || (hname_len == 2 && strncmp (hname, "to", 2) == 0) || (hname_len == 1 && strncmp (hname, "f", 1) == 0) || (hname_len == 4 && strncmp (hname, "from", 4) == 0) || (hname_len == 1 && strncmp (hname, "i", 1) == 0) || (hname_len == 7 && strncmp (hname, "call-id", 7) == 0) || (hname_len == 4 && strncmp (hname, "cseq", 4) == 0) || (hname_len == 1 && strncmp (hname, "s", 1) == 0) || (hname_len == 7 && strncmp (hname, "subject", 7) == 0) || (hname_len == 7 && strncmp (hname, "expires", 7) == 0) || (hname_len == 6 && strncmp (hname, "server", 6) == 0) || (hname_len == 10 && strncmp (hname, "user-agent", 10) == 0) || (hname_len == 16 && strncmp (hname, "www-authenticate", 16) == 0) || (hname_len == 19 && strncmp (hname, "authentication-info", 19) == 0) || (hname_len == 18 && strncmp (hname, "proxy-authenticate", 18) == 0) || (hname_len == 19 && strncmp (hname, "proxy-authorization", 19) == 0) || (hname_len == 25 && strncmp (hname, "proxy-authentication-info", 25) == 0) || (hname_len == 12 && strncmp (hname, "organization", 12) == 0) || (hname_len == 13 && strncmp (hname, "authorization", 13) == 0) || (hname_len == 1 && strncmp (hname, "r", 1) == 0) /* refer-to */ || (hname_len == 8 && strncmp (hname, "refer-to", 8) == 0) || (hname_len == 1 && strncmp (hname, "b", 1) == 0) /* referred-by */ || (hname_len == 11 && strncmp (hname, "referred-by", 11) == 0)) /* there is no multiple header! likely */ /* to happen most of the time... */ /* or hname is a TEXT-UTF8-TRIM and may */ /* contain a comma. this is not a separator */ /* THIS DOES NOT WORK FOR UNKNOWN HEADER!!!! */ { i = osip_message_set__header (sip, hname, hvalue); if (i != 0) return i; return OSIP_SUCCESS; } beg = hvalue; inquotes = 0; inuri = 0; /* Seach for a comma that is not within quotes or a URI */ for (;; ptr++) { switch (*ptr) { case '"': /* Check that the '"' is not escaped */ for (i = 0, p = ptr; p >= beg && *p == '\\'; p--, i++); if (i % 2 == 0) inquotes = !inquotes; /* the '"' was not escaped */ break; case '<': if (!inquotes) { if (!inuri) { if((osip_strncasecmp(ptr+1, "sip:", 4) == 0 || osip_strncasecmp(ptr+1, "sips:", 5) == 0 || osip_strncasecmp(ptr+1, "http:", 5) == 0 || osip_strncasecmp(ptr+1, "https:", 6) == 0 || osip_strncasecmp(ptr+1, "tel:", 4) == 0) && strchr(ptr, '>')) inuri = 1; } /* else { if we found such sequence: "<sip:" "<sip:" ">" It might be a valid header containing data and not URIs. Thus, we ignore inuri } */ } break; case '>': if (!inquotes) { if (inuri) inuri = 0; } break; case '\0': /* we discard any validation we tried: no valid uri detected */ inquotes=0; inuri=0; case ',': if (!inquotes && !inuri) { char *avalue; if (beg[0] == '\0') return OSIP_SUCCESS; /* empty header */ end = ptr; if (end - beg + 1 < 2) { beg=end+1; break; /* skip empty header */ } avalue = (char *) osip_malloc (end - beg + 1); if (avalue==NULL) return OSIP_NOMEM; osip_clrncpy (avalue, beg, end - beg); /* really store the header in the sip structure */ i = osip_message_set__header (sip, hname, avalue); osip_free (avalue); if (i != 0) return i; beg = end + 1; } if (*ptr == '\0') return OSIP_SUCCESS; break; default: break; } } }
int eXosip_get_srv_record(struct osip_srv_record *record, char *domain, char *protocol) { querybuf answer; /* answer buffer from nameserver */ int n; char zone[1024]; int ancount, qdcount; /* answer count and query count */ HEADER *hp; /* answer buffer header */ char hostbuf[256]; unsigned char *msg, *eom, *cp; /* answer buffer positions */ int dlen, type, aclass, pref, weight, port; long ttl; int answerno; char tr[100]; memset(zone, 0, sizeof(zone)); memset(record, 0, sizeof(struct osip_srv_record)); if (domain == NULL || protocol == NULL) return OSIP_BADPARAMETER; if (eXosip.dns_capabilities <= 0) return OSIP_UNKNOWN_HOST; /* disabled */ if (strlen(domain) + strlen(protocol) > 1000) return OSIP_BADPARAMETER; if (strlen(protocol) >= 100) return OSIP_BADPARAMETER; snprintf(tr, 100, protocol); osip_tolower(tr); if (eXosip.dns_capabilities >= 2) n = eXosip_get_naptr(domain, protocol, zone, sizeof(zone) - 1); else n = -1; /* avoid NAPTR */ if (n == OSIP_SUCCESS && zone[0] == '\0') { /* protocol is not listed in NAPTR answer: not supported */ return OSIP_UNKNOWN_HOST; } if (n != OSIP_SUCCESS) { snprintf(zone, sizeof(zone) - 1, "_sip._%s.%s", tr, domain); OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "Using locally generated SRV record %s\n", zone)); } OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "About to ask for '%s IN SRV'\n", zone)); n = res_query(zone, C_IN, T_SRV, (unsigned char *) &answer, sizeof(answer)); if (n < (int) sizeof(HEADER)) { return OSIP_UNKNOWN_HOST; } /* browse message and search for DNS answers part */ hp = (HEADER *) & answer; qdcount = ntohs(hp->qdcount); ancount = ntohs(hp->ancount); msg = (unsigned char *) (&answer); eom = (unsigned char *) (&answer) + n; cp = (unsigned char *) (&answer) + sizeof(HEADER); while (qdcount-- > 0 && cp < eom) { n = dn_expand(msg, eom, cp, (char *) hostbuf, 256); if (n < 0) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Invalid SRV record answer for '%s': bad format\n", zone)); return OSIP_UNDEFINED_ERROR; } cp += n + QFIXEDSZ; } /* browse DNS answers */ answerno = 0; /* loop through the answer buffer and extract SRV records */ while (ancount-- > 0 && cp < eom) { struct osip_srv_entry *srventry; n = dn_expand(msg, eom, cp, (char *) hostbuf, 256); if (n < 0) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Invalid SRV record answer for '%s': bad format\n", zone)); return OSIP_UNDEFINED_ERROR; } cp += n; #if defined(__NetBSD__) || defined(__OpenBSD__) ||\ defined(OLD_NAMESER) || defined(__FreeBSD__) type = _get_short(cp); cp += sizeof(u_short); #elif defined(__APPLE_CC__) GETSHORT(type, cp); #else NS_GET16(type, cp); #endif #if defined(__NetBSD__) || defined(__OpenBSD__) ||\ defined(OLD_NAMESER) || defined(__FreeBSD__) aclass = _get_short(cp); cp += sizeof(u_short); #elif defined(__APPLE_CC__) GETSHORT(aclass, cp); #else NS_GET16(aclass, cp); #endif #if defined(__NetBSD__) || defined(__OpenBSD__) ||\ defined(OLD_NAMESER) || defined(__FreeBSD__) ttl = _get_long(cp); cp += sizeof(u_long); #elif defined(__APPLE_CC__) GETLONG(ttl, cp); #else NS_GET32(ttl, cp); #endif #if defined(__NetBSD__) || defined(__OpenBSD__) ||\ defined(OLD_NAMESER) || defined(__FreeBSD__) dlen = _get_short(cp); cp += sizeof(u_short); #elif defined(__APPLE_CC__) GETSHORT(dlen, cp); #else NS_GET16(dlen, cp); #endif if (type != T_SRV) { cp += dlen; continue; } #if defined(__NetBSD__) || defined(__OpenBSD__) ||\ defined(OLD_NAMESER) || defined(__FreeBSD__) pref = _get_short(cp); cp += sizeof(u_short); #elif defined(__APPLE_CC__) GETSHORT(pref, cp); #else NS_GET16(pref, cp); #endif #if defined(__NetBSD__) || defined(__OpenBSD__) ||\ defined(OLD_NAMESER) || defined(__FreeBSD__) weight = _get_short(cp); cp += sizeof(u_short); #elif defined(__APPLE_CC__) GETSHORT(weight, cp); #else NS_GET16(weight, cp); #endif #if defined(__NetBSD__) || defined(__OpenBSD__) ||\ defined(OLD_NAMESER) || defined(__FreeBSD__) port = _get_short(cp); cp += sizeof(u_short); #elif defined(__APPLE_CC__) GETSHORT(port, cp); #else NS_GET16(port, cp); #endif n = dn_expand(msg, eom, cp, (char *) hostbuf, 256); if (n < 0) break; cp += n; srventry = &record->srventry[answerno]; snprintf(srventry->srv, sizeof(srventry->srv), "%s", hostbuf); srventry->priority = pref; srventry->weight = weight; if (weight) srventry->rweight = 1 + random() % (10000 * srventry->weight); else srventry->rweight = 0; srventry->port = port; OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "SRV record %s IN SRV -> %s:%i/%i/%i/%i\n", zone, srventry->srv, srventry->port, srventry->priority, srventry->weight, srventry->rweight)); answerno++; if (answerno == 10) break; } if (answerno == 0) return OSIP_UNKNOWN_HOST; osip_srv_record_sort(record, answerno); snprintf(record->name, sizeof(record->name), "%s", domain); return OSIP_SUCCESS; }
int eXosip_get_naptr(char *domain, char *protocol, char *srv_record, int max_length) { querybuf answer; /* answer buffer from nameserver */ int n; char zone[1024]; int ancount, qdcount; /* answer count and query count */ HEADER *hp; /* answer buffer header */ char hostbuf[256]; unsigned char *msg, *eom, *cp; /* answer buffer positions */ int dlen, type, aclass; long ttl; int answerno; char tr[100]; memset(srv_record, 0, max_length); if (domain == NULL || protocol == NULL) return OSIP_BADPARAMETER; if (strlen(domain) + strlen(protocol) > 1000) return OSIP_BADPARAMETER; if (strlen(protocol) >= 100) return OSIP_BADPARAMETER; snprintf(tr, 100, protocol); osip_tolower(tr); snprintf(zone, 1024, "%s", domain); OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "About to ask for '%s IN NAPTR\n", zone)); n = res_query(zone, C_IN, T_NAPTR, (unsigned char *) &answer, sizeof(answer)); if (n < (int) sizeof(HEADER)) { return OSIP_UNKNOWN_HOST; } /* browse message and search for DNS answers part */ hp = (HEADER *) & answer; qdcount = ntohs(hp->qdcount); ancount = ntohs(hp->ancount); msg = (unsigned char *) (&answer); eom = (unsigned char *) (&answer) + n; cp = (unsigned char *) (&answer) + sizeof(HEADER); while (qdcount-- > 0 && cp < eom) { n = dn_expand(msg, eom, cp, (char *) hostbuf, 256); if (n < 0) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Invalid SRV record answer for '%s': bad format\n", zone)); return OSIP_UNDEFINED_ERROR; } cp += n + QFIXEDSZ; } /* browse DNS answers */ answerno = 0; /* loop through the answer buffer and extract SRV records */ while (ancount-- > 0 && cp < eom) { int len; typedef struct { unsigned short order; unsigned short pref; char flag[256]; char service[1024]; char regexp[1024]; char replacement[1024]; } osip_naptr_t; osip_naptr_t anaptr; n = dn_expand(msg, eom, cp, (char *) hostbuf, 256); if (n < 0) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Invalid NAPTR answer for '%s': bad format\n", zone)); return OSIP_UNDEFINED_ERROR; } cp += n; #if defined(__NetBSD__) || defined(__OpenBSD__) ||\ defined(OLD_NAMESER) || defined(__FreeBSD__) type = _get_short(cp); cp += sizeof(u_short); #elif defined(__APPLE_CC__) GETSHORT(type, cp); #else NS_GET16(type, cp); #endif #if defined(__NetBSD__) || defined(__OpenBSD__) ||\ defined(OLD_NAMESER) || defined(__FreeBSD__) aclass = _get_short(cp); cp += sizeof(u_short); #elif defined(__APPLE_CC__) GETSHORT(aclass, cp); #else NS_GET16(aclass, cp); #endif #if defined(__NetBSD__) || defined(__OpenBSD__) ||\ defined(OLD_NAMESER) || defined(__FreeBSD__) ttl = _get_long(cp); cp += sizeof(u_long); #elif defined(__APPLE_CC__) GETLONG(ttl, cp); #else NS_GET32(ttl, cp); #endif #if defined(__NetBSD__) || defined(__OpenBSD__) ||\ defined(OLD_NAMESER) || defined(__FreeBSD__) dlen = _get_short(cp); cp += sizeof(u_short); #elif defined(__APPLE_CC__) GETSHORT(dlen, cp); #else NS_GET16(dlen, cp); #endif if (type != T_NAPTR) { cp += dlen; continue; } memset(&anaptr, 0, sizeof(osip_naptr_t)); memcpy((void *) &anaptr.order, cp, 2); anaptr.order = ntohs(anaptr.order); /*((unsigned short)cp[0] << 8) | ((unsigned short)cp[1]); */ cp += sizeof(unsigned short); memcpy((void *) &anaptr.pref, cp, 2); anaptr.pref = ntohs(anaptr.pref); /* ((unsigned short)cp[0] << 8) | ((unsigned short)cp[1]); */ cp += sizeof(unsigned short); len = *cp; cp++; strncpy(anaptr.flag, (char *) cp, len); anaptr.flag[len] = '\0'; cp += len; len = *cp; cp++; strncpy(anaptr.service, (char *) cp, len); anaptr.service[len] = '\0'; cp += len; len = *cp; cp++; strncpy(anaptr.regexp, (char *) cp, len); anaptr.regexp[len] = '\0'; cp += len; n = dn_expand(msg, eom, cp, anaptr.replacement, 1024 - 1); if (n < 0) break; cp += n; OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "NAPTR %s ->%i/%i/%s/%s/%s/%s\n", zone, anaptr.order, anaptr.pref, anaptr.flag, anaptr.service, anaptr.regexp, anaptr.replacement)); if (osip_strncasecmp(tr, "udp", 4) == 0 && osip_strncasecmp(anaptr.service, "SIP+D2U", 8) == 0) { snprintf(srv_record, max_length, "%s", anaptr.replacement); return OSIP_SUCCESS; } else if (osip_strncasecmp(tr, "tcp", 4) == 0 && osip_strncasecmp(anaptr.service, "SIP+D2T", 8) == 0) { snprintf(srv_record, max_length, "%s", anaptr.replacement); return OSIP_SUCCESS; } else if (osip_strncasecmp(tr, "udp-tls", 8) == 0 && osip_strncasecmp(anaptr.service, "SIPS+D2U", 9) == 0) { snprintf(srv_record, max_length, "%s", anaptr.replacement); return OSIP_SUCCESS; } else if (osip_strncasecmp(tr, "tls", 4) == 0 && osip_strncasecmp(anaptr.service, "SIPS+D2T", 9) == 0) { snprintf(srv_record, max_length, "%s", anaptr.replacement); return OSIP_SUCCESS; } else if (osip_strncasecmp(tr, "sctp", 5) == 0 && osip_strncasecmp(anaptr.service, "SIP+D2S", 8) == 0) { snprintf(srv_record, max_length, "%s", anaptr.replacement); return OSIP_SUCCESS; } answerno++; } if (answerno == 0) return OSIP_UNKNOWN_HOST; OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "protocol: %s is not supported by domain %s\n", protocol, domain)); return OSIP_SUCCESS; }
int eXosip_get_srv_record(struct osip_srv_record *record, char *domain, char *protocol) { char zone[1024]; PDNS_RECORD answer, tmp; /* answer buffer from nameserver */ int n; char tr[100]; memset(zone, 0, sizeof(zone)); memset(record, 0, sizeof(struct osip_srv_record)); if (domain == NULL || protocol == NULL) return OSIP_BADPARAMETER; if (eXosip.dns_capabilities <= 0) return OSIP_UNKNOWN_HOST; /* disabled */ if (strlen(domain) + strlen(protocol) > 1000) return OSIP_BADPARAMETER; if (strlen(protocol) >= 100) return OSIP_BADPARAMETER; snprintf(tr, 100, protocol); osip_tolower(tr); if (eXosip.dns_capabilities >= 2) n = eXosip_get_naptr(domain, protocol, zone, sizeof(zone) - 1); else n = -1; /* avoid NAPTR */ if (n == OSIP_SUCCESS && zone[0] == '\0') { /* protocol is not listed in NAPTR answer: not supported */ return OSIP_UNKNOWN_HOST; } if (n != OSIP_SUCCESS) { if (osip_strcasecmp(tr, "TLS") == 0) snprintf(zone, sizeof(zone) - 1, "_sips._tcp.%s", domain); else if (osip_strcasecmp(tr, "DTLS") == 0) snprintf(zone, sizeof(zone) - 1, "_sips._udp.%s", domain); else snprintf(zone, sizeof(zone) - 1, "_sip._%s.%s", tr, domain); OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "Using locally generated SRV record %s\n", zone)); } OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "About to ask for '%s IN SRV'\n", zone)); if (DnsQuery(zone, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &answer, NULL) != 0) { return OSIP_UNKNOWN_HOST; } n = 0; for (tmp = answer; tmp != NULL; tmp = tmp->pNext) { struct osip_srv_entry *srventry; DNS_SRV_DATA *data; if (tmp->wType != DNS_TYPE_SRV) continue; srventry = &record->srventry[n]; data = &tmp->Data.SRV; snprintf(srventry->srv, sizeof(srventry->srv), "%s", data->pNameTarget); srventry->priority = data->wPriority; srventry->weight = data->wWeight; if (srventry->weight) srventry->rweight = 1 + rand() % (10000 * srventry->weight); else srventry->rweight = 0; srventry->port = data->wPort; OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "SRV record %s IN SRV -> %s:%i/%i/%i/%i\n", zone, srventry->srv, srventry->port, srventry->priority, srventry->weight, srventry->rweight)); n++; if (n == 10) break; } DnsRecordListFree(answer, DnsFreeRecordList); if (n == 0) return OSIP_UNKNOWN_HOST; osip_srv_record_sort(record, n); snprintf(record->name, sizeof(record->name), "%s", domain); return OSIP_SUCCESS; }
int eXosip_get_naptr(char *domain, char *protocol, char *srv_record, int max_length) { char zone[1024]; PDNS_RECORD answer, tmp; /* answer buffer from nameserver */ int n; char tr[100]; memset(srv_record, 0, max_length); if (domain == NULL || protocol == NULL) return OSIP_BADPARAMETER; if (strlen(domain) + strlen(protocol) > 1000) return OSIP_BADPARAMETER; if (strlen(protocol) >= 100) return OSIP_BADPARAMETER; snprintf(tr, 100, protocol); osip_tolower(tr); snprintf(zone, 1024, "%s", domain); OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "About to ask for '%s NAPTR'\n", zone)); if (DnsQuery(zone, DNS_TYPE_NAPTR, DNS_QUERY_STANDARD, NULL, &answer, NULL) != 0) { return OSIP_UNKNOWN_HOST; } n = 0; for (tmp = answer; tmp != NULL; tmp = tmp->pNext) { char *buf = (char *) &tmp->Data; int len; OSVERSIONINFOEX ovi; typedef struct { unsigned short order; unsigned short pref; char flag[256]; char service[1024]; char regexp[1024]; char replacement[1024]; } osip_naptr_t; osip_naptr_t anaptr; if (tmp->wType != DNS_TYPE_NAPTR) continue; memset(&anaptr, 0, sizeof(osip_naptr_t)); memset(&ovi, 0, sizeof(ovi)); ovi.dwOSVersionInfoSize = sizeof(ovi); GetVersionEx((LPOSVERSIONINFO) & ovi); /* Minimum: client: Windows 2000 Professional */ /* Minimum: server: Windows 2000 Server */ OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "check OS support for NAPTR: %i %i %i\n", ovi.dwMajorVersion, ovi.dwMinorVersion, ovi.dwBuildNumber)); if (ovi.dwMajorVersion > 5) { #if (_WIN32_WINNT >= 0x0600) /* RUN only on Vista? */ /* compile starting from SDK 6.0A? even on XP... */ anaptr.order = tmp->Data.NAPTR.wOrder; anaptr.pref = tmp->Data.NAPTR.wPreference; strncpy(anaptr.flag, tmp->Data.NAPTR.pFlags, sizeof(anaptr.flag) - 1); strncpy(anaptr.service, tmp->Data.NAPTR.pService, sizeof(anaptr.service) - 1); strncpy(anaptr.regexp, tmp->Data.NAPTR.pRegularExpression, sizeof(anaptr.regexp) - 1); strncpy(anaptr.replacement, tmp->Data.NAPTR.pReplacement, sizeof(anaptr.replacement) - 1); #endif } else { memcpy((void *) &anaptr.order, buf, 2); anaptr.order = ntohs(anaptr.order); /* ((unsigned short)buf[0] << 8) | ((unsigned short)buf[1]); */ buf += sizeof(unsigned short); memcpy((void *) &anaptr.pref, buf, 2); anaptr.pref = ntohs(anaptr.pref); /* ((unsigned short)buf[0] << 8) | ((unsigned short)buf[1]); */ buf += sizeof(unsigned short); len = *buf; if (len < 0 || len > 255) break; buf++; strncpy(anaptr.flag, buf, len); anaptr.flag[len] = '\0'; buf += len; len = *buf; if (len < 0 || len > 1023) break; buf++; strncpy(anaptr.service, buf, len); anaptr.service[len] = '\0'; buf += len; len = *buf; if (len < 0 || len > 1023) break; buf++; strncpy(anaptr.regexp, buf, len); anaptr.regexp[len] = '\0'; buf += len; len = _eX_dn_expand((char *) &tmp->Data, ((char *) &tmp->Data) + tmp->wDataLength, buf, anaptr.replacement, 1024 - 1); if (len < 0) break; buf += len; } OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "NAPTR %s ->%i/%i/%s/%s/%s/%s\n", zone, anaptr.order, anaptr.pref, anaptr.flag, anaptr.service, anaptr.regexp, anaptr.replacement)); if (osip_strncasecmp(tr, "udp", 4) == 0 && osip_strncasecmp(anaptr.service, "SIP+D2U", 8) == 0) { snprintf(srv_record, max_length, "%s", anaptr.replacement); DnsRecordListFree(answer, DnsFreeRecordList); return OSIP_SUCCESS; } else if (osip_strncasecmp(tr, "tcp", 4) == 0 && osip_strncasecmp(anaptr.service, "SIP+D2T", 8) == 0) { snprintf(srv_record, max_length, "%s", anaptr.replacement); DnsRecordListFree(answer, DnsFreeRecordList); return OSIP_SUCCESS; } else if (osip_strncasecmp(tr, "udp-tls", 8) == 0 && osip_strncasecmp(anaptr.service, "SIPS+D2U", 9) == 0) { snprintf(srv_record, max_length, "%s", anaptr.replacement); DnsRecordListFree(answer, DnsFreeRecordList); return OSIP_SUCCESS; } else if (osip_strncasecmp(tr, "tls", 4) == 0 && osip_strncasecmp(anaptr.service, "SIPS+D2T", 9) == 0) { snprintf(srv_record, max_length, "%s", anaptr.replacement); DnsRecordListFree(answer, DnsFreeRecordList); return OSIP_SUCCESS; } else if (osip_strncasecmp(tr, "sctp", 5) == 0 && osip_strncasecmp(anaptr.service, "SIP+D2S", 8) == 0) { snprintf(srv_record, max_length, "%s", anaptr.replacement); DnsRecordListFree(answer, DnsFreeRecordList); return OSIP_SUCCESS; } n++; } DnsRecordListFree(answer, DnsFreeRecordList); if (n == 0) return OSIP_UNKNOWN_HOST; OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "protocol: %s is not supported by domain %s\n", protocol, domain)); return OSIP_SUCCESS; }