Back to index

courier  0.68.2
rfc1035.h
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 2011 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #ifndef       rfc1035_h
00007 #define       rfc1035_h
00008 
00009 
00010 
00011 #if    HAVE_CONFIG_H
00012 #include "rfc1035/config.h"
00013 #endif
00014 
00015 #include      "random128/random128.h"
00016 #include      "md5/md5.h"
00017 
00018 #include      <stdio.h>
00019 #include      <sys/types.h>
00020 #include      <sys/socket.h>
00021 #if HAVE_NETINET_IN_H
00022 #include      <netinet/in.h>
00023 #endif
00024 
00025 #ifdef  __cplusplus
00026 extern "C" {
00027 #endif
00028 
00029 #if RFC1035_IPV6
00030 typedef struct in6_addr     RFC1035_ADDR;
00031 typedef struct sockaddr_in6 RFC1035_SOCKADDR;
00032 typedef struct sockaddr_storage RFC1035_NETADDR;
00033 #define RFC1035_ADDRANY            in6addr_any
00034 #else
00035 typedef       struct in_addr       RFC1035_ADDR;
00036 typedef struct sockaddr_in  RFC1035_SOCKADDR;
00037 typedef struct sockaddr            RFC1035_NETADDR;
00038 
00039 extern struct in_addr rfc1035_addr_any;
00040 #define RFC1035_ADDRANY            rfc1035_addr_any
00041 #endif
00042 
00043 #define RFC1035_TYPE_A             1
00044 #define RFC1035_TYPE_NS            2
00045 #define RFC1035_TYPE_MD            3
00046 #define RFC1035_TYPE_MF            4
00047 #define RFC1035_TYPE_CNAME  5
00048 #define RFC1035_TYPE_SOA    6
00049 #define RFC1035_TYPE_MB            7
00050 #define RFC1035_TYPE_MG            8
00051 #define RFC1035_TYPE_MR            9
00052 #define RFC1035_TYPE_NULL   10
00053 #define RFC1035_TYPE_WKS    11
00054 #define RFC1035_TYPE_PTR    12
00055 #define RFC1035_TYPE_HINFO  13
00056 #define RFC1035_TYPE_MINFO  14
00057 #define RFC1035_TYPE_MX            15
00058 #define RFC1035_TYPE_TXT    16
00059 
00060 #define       RFC1035_TYPE_AAAA    28     /* RFC 1886. Even if we don't have
00061                                    IPv6 */
00062 
00063 #define RFC1035_TYPE_OPT    41
00064 #define RFC1035_TYPE_RRSIG  46
00065 
00066 #define       RFC1035_TYPE_AXFR    252
00067 #define       RFC1035_TYPE_MAILB   253
00068 #define       RFC1035_TYPE_MAILA   254
00069 #define       RFC1035_TYPE_ANY     255
00070 
00071 void rfc1035_type_itostr(int, void (*)(const char *, void *), void *);
00072 int rfc1035_type_strtoi(const char *);
00073 
00074 #define       RFC1035_CLASS_IN     1
00075 #define       RFC1035_CLASS_CSNET  2
00076 #define       RFC1035_CLASS_CHAOS  3
00077 #define       RFC1035_CLASS_HESIOD 4
00078 #define       RFC1035_CLASS_ANY    255
00079 
00080 const char *rfc1035_class_itostr(int);
00081 int rfc1035_class_strtoi(const char *);
00082 
00083 #define       RFC1035_OPCODE_QUERY 0
00084 #define       RFC1035_OPCODE_IQUERY       1
00085 #define       RFC1035_OPCODE_STATUS       2
00086 
00087 const char *rfc1035_opcode_itostr(int);
00088 int rfc1035_opcode_strtoi(const char *);
00089 
00090 #define RFC1035_RCODE_NOERROR      0
00091 #define       RFC1035_RCODE_FORMAT 1
00092 #define       RFC1035_RCODE_SERVFAIL      2
00093 #define       RFC1035_RCODE_NXDOMAIN      3
00094 #define       RFC1035_RCODE_UNIMPLEMENTED 4
00095 #define       RFC1035_RCODE_REFUSED       5
00096 
00097 const char *rfc1035_rcode_itostr(int);
00098 int rfc1035_rcode_strtoi(const char *);
00099 
00100 struct rfc1035_query {
00101        const char *name;
00102        unsigned qtype, qclass;
00103        } ;
00104 
00105 struct rfc1035_reply;       /* Defined below */
00106 struct rfc1035_rr;   /* Defined below */
00107 
00108 /*
00109 ** The init family of functions perform various initializations.  Calling them
00110 ** is optional, as librfc1035.a will use defaults if not specified.
00111 */
00112 
00113 #define       RFC1035_MAXNS 10
00114 #define       RFC1035_DEFAULT_INITIAL_TIMEOUT    5
00115 #define       RFC1035_DEFAULT_MAXIMUM_BACKOFF    3
00116 
00117               /* Resolver state */
00118 struct rfc1035_res {
00119 
00120        RFC1035_ADDR nameservers[RFC1035_MAXNS];
00121        int rfc1035_nnameservers;
00122 
00123        char *rfc1035_defaultdomain;
00124        int norecursive; /* Do not set the recursive flag, for specialized apps */
00125        int dnssec_payload_size; /* Enable dnssec requests */
00126 
00127        unsigned rfc1035_good_ns;
00128        unsigned rfc1035_timeout_initial;  /* Initial timeout */
00129        unsigned rfc1035_timeout_backoff;  /* Maximum exponential backoff */
00130 
00131        random128binbuf randseed;
00132        MD5_DIGEST    randbuf;
00133        unsigned randptr;
00134        } ;
00135 
00136 extern struct rfc1035_res rfc1035_default_resolver;
00137 
00138 void rfc1035_init_timeout(struct rfc1035_res *, unsigned, unsigned);
00139                                    /*
00140                                    ** Specify timeout in seconds,
00141                                    ** and maximum exponential backoff.
00142                                    */
00143 void rfc1035_init_ns(struct rfc1035_res *, const RFC1035_ADDR *, unsigned);
00144               /* Specify nameservers to query (max 10) */
00145 
00146 void rfc1035_init_norecursive(struct rfc1035_res *, int);
00147        /* Set the no-recursive flag, if you don't want the NS to do recursive queries on your behalf */
00148 
00149 void rfc1035_init_dnssec_enable(struct rfc1035_res *, int);
00150        /* Enable/disable dnssec/edns0 */
00151 
00152 void rfc1035_init_edns_payload(struct rfc1035_res *, int);
00153        /* Set edns0 payload size */
00154 
00155 void rfc1035_init_resolv(struct rfc1035_res *);
00156        /* Read /etc/resolv.conf for nameservers */
00157 
00158 void rfc1035_destroy_resolv(struct rfc1035_res *);
00159        /* Destroy the resolver object */
00160 
00161        /*
00162        ** Most people will only need to call rfc1035_resolve or
00163        ** rfc1035_resolve_cname.  The return value from _resolve functions
00164        ** should be interpreted as follows:
00165        **     NULL - internal failure (treat it as a soft DNS error)
00166        **     ptr->rcode = RFC1035_RCODE_NOERROR - success
00167        **     ptr->rcode = RFC1035_RCODE_NXDOMAIN - hard DNS error
00168        **     ptr->rcode = RFC1035_RCODE_TEMPFAIL - soft DNS error
00169        **     ptr->rcode = any other value - log abnormal result,
00170        **                  handle as soft DNS error
00171        */
00172 
00173 struct rfc1035_reply *rfc1035_resolve(
00174        struct rfc1035_res *,       /* Pointer to a resolver structure */
00175        int,          /* Opcode, see above. */
00176        const char *, /* Query name */
00177        unsigned,     /* Query type, see above. */
00178        unsigned);    /* Query class, see above. */
00179 
00180        /*
00181        ** Multiple queries.  Most servers don't support this.
00182        */
00183 
00184 struct rfc1035_reply *rfc1035_resolve_multiple(
00185        struct rfc1035_res *,       /* Pointer to a resolver structure */
00186        int,   /* opcode */
00187        const struct rfc1035_query *,      /* Array of queries */
00188        unsigned);                  /* Array size */
00189 
00190 /*
00191 ** rfc1035_resolve_cname is like _resolve, but starts with the default
00192 ** servers, and automatically reissues the query if the received response
00193 ** is a CNAME.  If successful, it returns an INDEX into the allrrs array
00194 ** containing the first answer.  To get the next answers, call
00195 ** rfc1035_replysearch_all with return value+1.  If not succesfull, -1
00196 ** is returned.
00197 **
00198 ** Note - if the returned index points to a CNAME, this is because a CNAME
00199 ** pointed to another CNAME -- it's BAD!
00200 **
00201 ** It takes a POINTER to the 'id' counter, which is incremented if a
00202 ** second query needs to be issued.
00203 **
00204 ** If takes a POINTER to the rfc1035_reply structure, which will be either
00205 ** null on exit, or point to the reply received.  The pointer MAY be not null
00206 ** even if the return value is -1.
00207 **
00208 ** Suggested logic:
00209 **    Return value >= 0, succesfull query.
00210 **    Return value <= -1, ptr is not null, and rcode = RFC1035_RCODE_NXDOMAIN,
00211 **        hard DNS error.
00212 **    Return value <= -1, ptr is not null, and rcode = RFC1035_RCODE_TEMPFAIL,
00213 **        soft DNS error.
00214 **    Other situations: log the abnormal result, handle as soft DNS error.
00215 */
00216 
00217 #define       RFC1035_ERR_CNAME_RECURSIVE -2
00218        /* Specific error code for a recursive CNAME record - prohibited */
00219 
00220 int rfc1035_resolve_cname(
00221               struct rfc1035_res *,       /* Pointer to a resolver structure */
00222               char *,                     /* RFC1035_MAXNAMESIZE buffer with
00223                                    ** the name to query */
00224               unsigned,            /* Query type */
00225               unsigned,            /* Query class */
00226               struct rfc1035_reply **, /* Ptr set to reply received */
00227               int); /* Extended flags: */
00228 
00229 #define RFC1035_X_RANDOMIZE 1    /* Randomize query results */
00230 
00231        /*
00232        ** Always call replyfree when done.
00233        */
00234 
00235 void rfc1035_replyfree(struct rfc1035_reply *);
00236 
00237        /*
00238        ** !!!ALL!!! the const char * pointers in rfc1035_reply are NOT
00239        ** standard C strings, but DNS-compressed strings.  Call
00240        ** replyhostname to translate those to C strings.
00241        */
00242 
00243 const char *rfc1035_replyhostname(
00244        const struct rfc1035_reply *,      /* The reply */
00245        const char *, /* The const char ptr */
00246 
00247        char *);      /* Buffer where to put hostname.  All strings are
00248                      ** guaranteed to fit into RFC1035_MAXNAMESIZE+1 byte
00249                      ** buffer.
00250                      ** replyhostname returns this pointer.
00251                      */
00252 
00253 /* Some value added code, look up A and PTR records. */
00254 
00255 int rfc1035_a(struct rfc1035_res *,
00256        const char *,        /* Host name */
00257        RFC1035_ADDR **,            /* We allocate array of IP addresses */
00258        unsigned *);                /* We return # of IP addresses here */
00259 
00260 int rfc1035_ptr(struct rfc1035_res *,
00261        const RFC1035_ADDR *,       /* Query PTR for this address */
00262        char *);             /* Result - RFC1035_MAXNAMESIZE+1 buf */
00263 
00264 int rfc1035_ptr_x(struct rfc1035_res *res, const RFC1035_ADDR *addr,
00265                 void (*cb_func)(const char *, void *),
00266                 void *cb_arg); /* Invoke a callback function instead
00267                              ** (multiple callbacks possible)
00268                              */
00269 
00270 /* ---------------------- */
00271 
00272        /* Replyuncompress is a lower-level function taking a pointer to
00273        ** the const char *.  When it returns, the const char * is advanced
00274        ** past the end of the compressed string in the DNS data.
00275        ** replyuncompress returns its third argument, or NULL if there was
00276        ** an error. */
00277 
00278 const char *rfc1035_replyuncompress(const char **,
00279        const struct rfc1035_reply *, char *);
00280 
00281 #define       RFC1035_MAXNAMESIZE  255
00282 
00283 
00284        /*
00285        ** Compare two hostnames.  Return 0 if they match, non-zero if they
00286        ** don't.
00287        */
00288 
00289 int rfc1035_hostnamecmp(const char *, const char *);
00290 
00291        /*
00292        ** After we receive a reply, search for the answer there.  Returns
00293        ** an index in the respective section, or -1 if not found.
00294        ** If we find a CNAME, we return a pointer to it instead, so make
00295        ** sure to check for that!
00296        */
00297 
00298 int rfc1035_replysearch_an(
00299        const struct rfc1035_res *, /* The resolver */
00300        const struct rfc1035_reply *,      /* The reply */
00301        const char *,                      /* Hostname to search */
00302        unsigned,                   /* Type */
00303        unsigned,                   /* Class */
00304        int);                       /* Starting position, 1st time use 0 */
00305 
00306 int rfc1035_replysearch_ns(
00307        const struct rfc1035_res *, /* The resolver */
00308        const struct rfc1035_reply *,      /* The reply */
00309        const char *,                      /* Hostname to search */
00310        unsigned,                   /* Type */
00311        unsigned,                   /* Class */
00312        int);                       /* Starting position, 1st time use 0 */
00313 
00314 int rfc1035_replysearch_all(
00315        const struct rfc1035_res *, /* The resolver */
00316        const struct rfc1035_reply *,      /* The reply */
00317        const char *,                      /* Hostname to search */
00318        unsigned,                   /* Type */
00319        unsigned,                   /* Class */
00320        int);                       /* Starting position, 1st time use 0 */
00321 
00322 /*
00323 ** Low level functions follow.
00324 */
00325 
00326        /*
00327        ** rfc1035_mkquery() constructs a query to be sent.  The query is
00328        ** composed by REPEATEDLY running the caller-provided function,
00329        ** which will be called REPEATEDLY to build the query, part by part.
00330        */
00331 
00332 int rfc1035_mkquery(struct rfc1035_res *, /* resolver structure */
00333                      unsigned,     /* opcode */
00334 
00335 #define       RFC1035_RESOLVE_RECURSIVE 1 /* Ask nameserver to do the recursion */
00336 
00337                      const struct rfc1035_query *,      /* questions */
00338                      unsigned,     /* Number of questions */
00339                      void (*)(const char *, unsigned, void *),
00340                                    /* Function - called repetitively
00341                                    ** to build the query */
00342                      void *);      /* Third arg to function */
00343 
00344 /**************************************************************************/
00345 /* Low level input/output functions.  Most people won't need to use these */
00346 /**************************************************************************/
00347 
00348 int rfc1035_open_udp(int *af);            /* Create a UDP socket */
00349 
00350 int rfc1035_send_udp(int,   /* File descriptor from rfc1035_open */
00351               const struct sockaddr *, int, /* Send to this name server */
00352               const char *, /* The query */
00353               unsigned);    /* Query length */
00354        /*
00355        ** Returns 0, or non-zero if failed.
00356        */
00357 
00358 int rfc1035_wait_reply(int, /* File descriptor from rfc1035_open */
00359        unsigned);    /* Number of seconds to wait, use 0 for default */
00360        /* Returns 0 when reply is waiting, non-0 if timeout expired */
00361 
00362 int rfc1035_wait_query(int, /* File descriptor from rfc1035_open */
00363        unsigned);    /* Number of seconds to wait, use 0 for default */
00364        /* Like reply, but we select for writing */
00365 
00366 char *rfc1035_recv_udp(int, /* File descriptor from rfc1035_open */
00367        const struct sockaddr *, int,
00368                             /* Expecting reply from this IP address  */
00369        int *,        /* * will be set to point to # of bytes received */
00370        const char *);       /* Original query, used to validate id # */
00371        /* Returns ptr to dynamically allocated memory containing the reply,
00372        ** or NULL if error.  Errno will be set EAGAIN if we should try
00373        ** again, because the message received was not in response
00374        ** to the query.
00375        */
00376 
00377 char *rfc1035_query_udp(struct rfc1035_res *,
00378        int,   /* file descriptor */
00379        const struct sockaddr *, int,      /* Attempt number */
00380        const char *,        /* query */
00381        unsigned,            /* query length */
00382        int *,               /* # of bytes received */
00383        unsigned);           /* # of seconds to wait for response */
00384 
00385        /*
00386        ** Jumbo function: sends the indicated query via UDP, waits for
00387        ** a validated reply.  Returns pointer to dynamically allocated
00388        ** memory with the reply.  Returns NULL if there was an error.
00389        ** errno will be set to EAGAIN if the response timed out
00390        ** (if the UDP stack returns an error, we fake an EAGAIN).
00391        ** After getting EAGAIN, attempt number should be incremented,
00392        ** and we should try again.
00393        ** Fake ETIMEDOUT is returned if no more attempts are possible.
00394        */
00395 
00396 int rfc1035_open_tcp(struct rfc1035_res *, const RFC1035_ADDR *);
00397                             /*
00398                             ** Create a TCP socket for this attempt #,
00399                             ** returns negative for a failure, and sets
00400                             ** errno.
00401                             */
00402 
00403        /*
00404        ** Attempt to transmit the indicated query on this TCP socket.
00405        ** Return 0 for successfull transmission.
00406        */
00407 
00408 int rfc1035_send_tcp(int,   /* file descriptor */
00409               const char *, /* query */
00410               unsigned);    /* query length */
00411 
00412        /*
00413        ** Attempt to receive a reply on this TCP socket.
00414        ** Returns pointer to dynamically malloced memory, or null if error.
00415        */
00416 
00417 char *rfc1035_recv_tcp(struct rfc1035_res *,
00418               int,   /* file descriptor */
00419               int *,        /* * initialized to contain msg length */
00420               unsigned);    /* # of seconds to wait for a response */
00421 
00422 char *rfc1035_query_tcp(struct rfc1035_res *,
00423        int,   /* file descriptor */
00424        const char *,        /* query */
00425        unsigned,            /* query length */
00426        int *,               /* * initialized to contain msg length */
00427        unsigned);           /* # of seconds to wait for response */
00428 
00429 /*************************************************/
00430 /* Parse a raw response into a useful structure. */
00431 /*************************************************/
00432 
00433 struct rfc1035_rr {
00434        const char *rrname;  /* NOT a null term str, a ptr into the raw resp */
00435        unsigned rrtype, rrclass;
00436        RFC1035_UINT32  ttl;
00437        unsigned rdlength;
00438        const char    *rdata;       /* Raw data, parsed record follows: */
00439 
00440        union {
00441               struct {
00442                      const char *hinfo_str;
00443                      const char *os_str;
00444                      } hinfo;
00445 
00446               struct in_addr inaddr;             /* A */
00447 #if RFC1035_IPV6
00448               struct in6_addr in6addr;    /* AAAA */
00449 #endif
00450 
00451               const char *domainname;
00452                             /* CNAME, MB, MD, MF, MG, MR, NS, PTR */
00453 
00454               struct {
00455                      const char *rmailbx_label;
00456                      const char *emailbx_label;
00457                      } minfo;
00458 
00459               struct {
00460                      unsigned preference;
00461                      const char *mx_label;
00462                      } mx;
00463 
00464               struct {
00465                      const char *mname_label;
00466                      const char *rname_label;
00467                      RFC1035_UINT32 serial;
00468                      RFC1035_UINT32 refresh;
00469                      RFC1035_UINT32 retry;
00470                      RFC1035_UINT32 expire;
00471                      RFC1035_UINT32 minimum;
00472                      } soa;
00473 
00474               struct {
00475                      RFC1035_UINT16 type_covered;
00476                      unsigned char algorithm;
00477                      unsigned char labels;
00478                      RFC1035_UINT16 original_ttl;
00479                      RFC1035_UINT32 signature_expiration;
00480                      RFC1035_UINT32 signature_inception;
00481                      RFC1035_UINT16 key_tag;
00482                      const char *signer_name;
00483                      const char *signature;
00484                      RFC1035_UINT16 signature_len;
00485               } rrsig;
00486 
00487               /* As are just represented by rdata/rdlength */
00488               /* TXTs are parsed directly from rdata/rdlength */
00489               /* WKS are parsed directly */
00490 
00491               } rr;
00492        } ;
00493 
00494 struct rfc1035_reply {
00495        struct rfc1035_reply *next; /* AXFRs have a linked list here */
00496 
00497        const  char   *reply;       /* The raw reply, for convenience's sake */
00498        unsigned      replylen;     /* The length of the reply */
00499        char          *mallocedbuf; /* If not NULL, dynamically allocated
00500                                    ** memory that holds the reply.
00501                                    */
00502 
00503        RFC1035_NETADDR server_addr;       /* Replying server */
00504 
00505        unsigned char qr;
00506        unsigned char opcode;
00507        unsigned char aa;
00508        unsigned char tc;
00509        unsigned char rd;
00510        unsigned char ra;
00511        unsigned char ad;
00512        unsigned char cd;
00513        unsigned char rcode;
00514        unsigned qdcount;
00515        unsigned ancount;
00516        unsigned nscount;
00517        unsigned arcount;
00518 
00519        struct rfc1035_query *qdptr;       /* sizeof qdcount */
00520        struct rfc1035_rr *anptr;
00521        struct rfc1035_rr *nsptr;
00522        struct rfc1035_rr *arptr;
00523 
00524        struct rfc1035_rr **allrrs; /* Pointers to all RR records,
00525                                    ** add ancount+nscount+arcount for
00526                                    ** the size of the array */
00527        } ;
00528 
00529 struct rfc1035_reply *rfc1035_replyparse(const char *, unsigned);
00530 void rfc1035_rr_rand_an(struct rfc1035_reply *rr);
00531 void rfc1035_rr_rand_ns(struct rfc1035_reply *rr);
00532 void rfc1035_rr_rand_ar(struct rfc1035_reply *rr);
00533 void rfc1035_rr_rand(struct rfc1035_reply *rr);
00534 
00535 void rfc1035_dump(struct rfc1035_reply *, FILE *);
00536 
00537 const char *rfc1035_fmttime(unsigned long, char *);
00538 #define       RFC1035_MAXTIMEBUFSIZE      40
00539 
00540 char *rfc1035_dumprrdata(struct rfc1035_reply *, struct rfc1035_rr *);
00541 
00542 int rfc1035_rr_gettxt(struct rfc1035_rr *,
00543        int,
00544        char buf[256]);
00545 
00546 /*
00547 ** I ignore any possible bugs in the resolver functions, and roll my own,
00548 ** for IPv4.
00549 */
00550 
00551 void rfc1035_ntoa_ipv4(const struct in_addr *in, char *buf);
00552 int rfc1035_aton_ipv4(const char *p, struct in_addr *in4);
00553 
00554 #if RFC1035_IPV6
00555 void rfc1035_ipv6to4(struct in_addr *, const struct in6_addr *);
00556 void rfc1035_ipv4to6(struct in6_addr *, const struct in_addr *);
00557 #endif
00558 
00559 /*
00560 ** Extract network address from a socket address.
00561 */
00562 
00563 int rfc1035_sockaddrip(const RFC1035_NETADDR *,  /* Socket address buffer */
00564               int,                        /* Length of address */
00565               RFC1035_ADDR *);            /* Address saved here */
00566 
00567 int rfc1035_sockaddrport(const RFC1035_NETADDR *, /* Socket address buffer */
00568               int,                        /* Length of address */
00569               int *);                            /* Port saved here */
00570 
00571 #if RFC1035_IPV6
00572 #define       RFC1035_NTOABUFSIZE  INET6_ADDRSTRLEN
00573 #else
00574 #define       RFC1035_NTOABUFSIZE  16
00575 #endif
00576 
00577 void rfc1035_ntoa(const RFC1035_ADDR *, char *);
00578 int rfc1035_aton(const char *, RFC1035_ADDR *);
00579 
00580 /*
00581 ** New function that compares two addresses -- handles both IPv4 and IPv6:
00582 */
00583 
00584 int rfc1035_same_ip(const void *, int, const void *, int);
00585 
00586 int     rfc1035_bindsource(int sockfd,    /* Socket fd */
00587        const struct sockaddr *addr,       /* Buffer to socket address */
00588        int addrlen);               /* Size of socket address */
00589 
00590 /*
00591 ** First try to create an IPv6 socket, then, if we fail, an IPv4 socket.
00592 */
00593 
00594 int    rfc1035_mksocket(int sock_type,           /* socket type to create */
00595                      int sock_protocol,   /* socket protocol to create */
00596                      int *af);     /* If succeed, address family created */
00597 
00598 /*
00599 ** Take the destination address, and create a socket address structure
00600 ** suitable for connecting to this address.
00601 */
00602 
00603 int    rfc1035_mkaddress(int af,          /* AF_INET or AF_INET6 */
00604 
00605        /* buf is initiailized to the sender's ip address. */
00606 
00607        RFC1035_NETADDR *buf,              /* Buffer for the created address */
00608        const RFC1035_ADDR *addr,   /* Network address */
00609        int port,                   /* Network port (network byte order) */
00610        const struct sockaddr **ptr,       /* Will point to buf */
00611        int *len);                  /* Will be size of socket address */
00612 
00613 /*
00614 ** A convenient interface to the SIOCGIFCONF ioctl.
00615 */
00616 
00617 struct rfc1035_ifconf {
00618        struct rfc1035_ifconf *next;
00619        char *ifname;
00620        RFC1035_ADDR ifaddr;
00621 };
00622 
00623 struct rfc1035_ifconf *rfc1035_ifconf(int *errflag);
00624 void rfc1035_ifconf_free(struct rfc1035_ifconf *ifconf_list);
00625 
00626 #ifdef  __cplusplus
00627 }
00628 #endif
00629 
00630 #endif