Main Page | Alphabetical List | Data Structures | Directories | 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 #include <asterisk/utils.h>
00031 
00032 #ifdef __APPLE__
00033 #undef T_SRV
00034 #define T_SRV 33
00035 #endif
00036 
00037 struct srv {
00038    unsigned short priority;
00039    unsigned short weight;
00040    unsigned short portnum;
00041 } __attribute__ ((__packed__));
00042 
00043 static int parse_srv(unsigned char *host, int hostlen, int *portno, unsigned char *answer, int len, unsigned char *msg)
00044 {
00045    int res = 0;
00046    struct srv *srv = (struct srv *)answer;
00047    char repl[256] = "";
00048 
00049    if (len < sizeof(struct srv)) {
00050       printf("Length too short\n");
00051       return -1;
00052    }
00053    answer += sizeof(struct srv);
00054    len -= sizeof(struct srv);
00055 
00056    if ((res = dn_expand(msg,answer + len,answer, repl, sizeof(repl) - 1)) < 0) {
00057       ast_log(LOG_WARNING, "Failed to expand hostname\n");
00058       return -1;
00059    }
00060    if (res && strcmp(repl, ".")) {
00061       if (option_verbose > 3)
00062          ast_verbose( VERBOSE_PREFIX_3 "parse_srv: SRV mapped to host %s, port %d\n", repl, ntohs(srv->portnum));
00063       if (host) {
00064          strncpy(host, repl, hostlen - 1);
00065          host[hostlen-1] = '\0';
00066       }
00067       if (portno)
00068          *portno = ntohs(srv->portnum);
00069       return(0);
00070    }
00071    return(-1);
00072 }
00073 
00074 struct srv_context {
00075    char *host;
00076    int hostlen;
00077    int *port;
00078 };
00079 
00080 static int srv_callback(void *context, u_char *answer, int len, u_char *fullanswer)
00081 {
00082    struct srv_context *c = (struct srv_context *)context;
00083 
00084    if (parse_srv(c->host, c->hostlen, c->port, answer, len, fullanswer)) {
00085       ast_log(LOG_WARNING, "Failed to parse srv\n");
00086       return -1;
00087    }
00088 
00089    if (!ast_strlen_zero(c->host))
00090       return 1;
00091 
00092    return 0;
00093 }
00094 
00095 int ast_get_srv(struct ast_channel *chan, char *host, int hostlen, int *port, const char *service)
00096 {
00097    struct srv_context context;
00098    int ret;
00099 
00100    context.host = host;
00101    context.hostlen = hostlen;
00102    context.port = port;
00103 
00104    if (chan && ast_autoservice_start(chan) < 0)
00105       return -1;
00106 
00107    ret = ast_search_dns(&context, service, C_IN, T_SRV, srv_callback);
00108 
00109    if (chan)
00110       ret |= ast_autoservice_stop(chan);
00111 
00112    if (ret <= 0) {
00113       host[0] = '\0';
00114       *port = -1;
00115       return ret;
00116    }
00117    return ret;
00118 }

Generated on Wed Mar 16 20:08:36 2005 for Asterisk by  doxygen 1.4.0