Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

srv.c

Go to the documentation of this file.
00001 /*
00002  * ENUM Support for Asterisk
00003  *
00004  * Copyright (C) 2003 Digium
00005  *
00006  * Written by Mark Spencer <markster@digium.com>
00007  *
00008  * Funding provided by nic.at
00009  *
00010  * Distributed under the terms of the GNU GPL
00011  *
00012  */
00013 
00014 #include <sys/types.h>
00015 #include <netinet/in.h>
00016 #include <arpa/nameser.h>
00017 #if __APPLE_CC__ >= 1495
00018 #include <arpa/nameser_compat.h>
00019 #endif
00020 #include <resolv.h>
00021 #include <stdio.h>
00022 #include <string.h>
00023 #include <unistd.h>
00024 
00025 #include <asterisk/channel.h>
00026 #include <asterisk/logger.h>
00027 #include <asterisk/srv.h>
00028 #include <asterisk/dns.h>
00029 #include <asterisk/options.h>
00030 
00031 #ifdef __APPLE__
00032 #undef T_SRV
00033 #define T_SRV 33
00034 #endif
00035 
00036 struct srv {
00037    unsigned short priority;
00038    unsigned short weight;
00039    unsigned short portnum;
00040 } __attribute__ ((__packed__));
00041 
00042 static int parse_srv(unsigned char *host, int hostlen, int *portno, unsigned char *answer, int len, unsigned char *msg)
00043 {
00044    int res = 0;
00045    struct srv *srv = (struct srv *)answer;
00046    char repl[256] = "";
00047 
00048    if (len < sizeof(struct srv)) {
00049       printf("Length too short\n");
00050       return -1;
00051    }
00052    answer += sizeof(struct srv);
00053    len -= sizeof(struct srv);
00054 
00055    if ((res = dn_expand(msg,answer + len,answer, repl, sizeof(repl) - 1)) < 0) {
00056       ast_log(LOG_WARNING, "Failed to expand hostname\n");
00057       return -1;
00058    }
00059    if (res && strcmp(repl, ".")) {
00060       ast_verbose( VERBOSE_PREFIX_3 "parse_srv: SRV mapped to host %s, port %d\n", repl, ntohs(srv->portnum));
00061       if (host) {
00062          strncpy(host, repl, hostlen - 2);
00063          host[hostlen-1] = '\0';
00064       }
00065       if (portno)
00066          *portno = ntohs(srv->portnum);
00067       return(0);
00068    }
00069    return(-1);
00070 }
00071 
00072 struct srv_context {
00073    char *host;
00074    int hostlen;
00075    int *port;
00076 };
00077 
00078 static int srv_callback(void *context, u_char *answer, int len, u_char *fullanswer)
00079 {
00080    struct srv_context *c = (struct srv_context *)context;
00081 
00082    if (parse_srv(c->host, c->hostlen, c->port, answer, len, fullanswer))
00083       ast_log(LOG_WARNING, "Failed to parse srv\n");
00084 
00085    if (strlen(c->host))
00086       return 1;
00087 
00088     return 0;
00089 }
00090 
00091 int ast_get_srv(struct ast_channel *chan, char *host, int hostlen, int *port, const char *service)
00092 {
00093    struct srv_context context;
00094    int ret;
00095 
00096    context.host = host;
00097    context.hostlen = hostlen;
00098    context.port = port;
00099 
00100    if (chan && ast_autoservice_start(chan) < 0)
00101       return -1;
00102 
00103    ret = ast_search_dns(&context, service, C_IN, T_SRV, srv_callback);
00104 
00105    if (chan)
00106       ret |= ast_autoservice_stop(chan);
00107 
00108    if (ret <= 0) {
00109       strcpy(host, "");
00110          *port = -1;
00111       return ret;
00112    }
00113    return ret;
00114 }

Generated on Fri Feb 27 12:19:44 2004 for Asterisk by doxygen 1.3.5