rev |
line source |
yuuji@0
|
1 /* ========================================================================
|
yuuji@0
|
2 * Copyright 1988-2006 University of Washington
|
yuuji@0
|
3 *
|
yuuji@0
|
4 * Licensed under the Apache License, Version 2.0 (the "License");
|
yuuji@0
|
5 * you may not use this file except in compliance with the License.
|
yuuji@0
|
6 * You may obtain a copy of the License at
|
yuuji@0
|
7 *
|
yuuji@0
|
8 * http://www.apache.org/licenses/LICENSE-2.0
|
yuuji@0
|
9 *
|
yuuji@0
|
10 *
|
yuuji@0
|
11 * ========================================================================
|
yuuji@0
|
12 */
|
yuuji@0
|
13
|
yuuji@0
|
14 /*
|
yuuji@0
|
15 * Program: UNIX IPv4 routines
|
yuuji@0
|
16 *
|
yuuji@0
|
17 * Author: Mark Crispin
|
yuuji@0
|
18 * Networks and Distributed Computing
|
yuuji@0
|
19 * Computing & Communications
|
yuuji@0
|
20 * University of Washington
|
yuuji@0
|
21 * Administration Building, AG-44
|
yuuji@0
|
22 * Seattle, WA 98195
|
yuuji@0
|
23 * Internet: MRC@CAC.Washington.EDU
|
yuuji@0
|
24 *
|
yuuji@0
|
25 * Date: 18 December 2003
|
yuuji@0
|
26 * Last Edited: 30 August 2006
|
yuuji@0
|
27 */
|
yuuji@0
|
28
|
yuuji@0
|
29 #define SADRLEN sizeof (struct sockaddr)
|
yuuji@0
|
30
|
yuuji@0
|
31 #define SADR4(sadr) ((struct sockaddr_in *) sadr)
|
yuuji@0
|
32 #define SADR4LEN sizeof (struct sockaddr_in)
|
yuuji@0
|
33 #define SADR4ADR(sadr) SADR4 (sadr)->sin_addr
|
yuuji@0
|
34 #define ADR4LEN sizeof (struct in_addr)
|
yuuji@0
|
35 #define SADR4PORT(sadr) SADR4 (sadr)->sin_port
|
yuuji@0
|
36
|
yuuji@0
|
37
|
yuuji@0
|
38 /* IP abstraction layer */
|
yuuji@0
|
39
|
yuuji@0
|
40 char *ip_sockaddrtostring (struct sockaddr *sadr);
|
yuuji@0
|
41 long ip_sockaddrtoport (struct sockaddr *sadr);
|
yuuji@0
|
42 void *ip_stringtoaddr (char *text,size_t *len,int *family);
|
yuuji@0
|
43 struct sockaddr *ip_newsockaddr (size_t *len);
|
yuuji@0
|
44 struct sockaddr *ip_sockaddr (int family,void *adr,size_t adrlen,
|
yuuji@0
|
45 unsigned short port,size_t *len);
|
yuuji@0
|
46 char *ip_sockaddrtoname (struct sockaddr *sadr);
|
yuuji@0
|
47 void *ip_nametoaddr (char *name,size_t *len,int *family,char **canonical,
|
yuuji@0
|
48 void **next);
|
yuuji@0
|
49
|
yuuji@0
|
50 /* Return IP address string from socket address
|
yuuji@0
|
51 * Accepts: socket address
|
yuuji@0
|
52 * Returns: IP address as name string
|
yuuji@0
|
53 */
|
yuuji@0
|
54
|
yuuji@0
|
55 char *ip_sockaddrtostring (struct sockaddr *sadr)
|
yuuji@0
|
56 {
|
yuuji@0
|
57 return (sadr->sa_family == PF_INET) ?
|
yuuji@0
|
58 inet_ntoa (SADR4ADR (sadr)) : "NON-IPv4";
|
yuuji@0
|
59 }
|
yuuji@0
|
60
|
yuuji@0
|
61
|
yuuji@0
|
62 /* Return port from socket address
|
yuuji@0
|
63 * Accepts: socket address
|
yuuji@0
|
64 * Returns: port number or -1 if can't determine it
|
yuuji@0
|
65 */
|
yuuji@0
|
66
|
yuuji@0
|
67 long ip_sockaddrtoport (struct sockaddr *sadr)
|
yuuji@0
|
68 {
|
yuuji@0
|
69 return (sadr->sa_family == PF_INET) ? ntohs (SADR4PORT (sadr)) : -1;
|
yuuji@0
|
70 }
|
yuuji@0
|
71
|
yuuji@0
|
72
|
yuuji@0
|
73 /* Return IP address from string
|
yuuji@0
|
74 * Accepts: name string
|
yuuji@0
|
75 * pointer to returned length
|
yuuji@0
|
76 * pointer to returned address family
|
yuuji@0
|
77 * Returns: address if valid, length and family updated, or NIL
|
yuuji@0
|
78 */
|
yuuji@0
|
79
|
yuuji@0
|
80 void *ip_stringtoaddr (char *text,size_t *len,int *family)
|
yuuji@0
|
81 {
|
yuuji@0
|
82 unsigned long adr;
|
yuuji@0
|
83 struct in_addr *ret;
|
yuuji@0
|
84 /* get address */
|
yuuji@0
|
85 if ((adr = inet_addr (text)) == -1) ret = NIL;
|
yuuji@0
|
86 else { /* make in_addr */
|
yuuji@0
|
87 ret = (struct in_addr *) fs_get (*len = ADR4LEN);
|
yuuji@0
|
88 *family = AF_INET; /* IPv4 */
|
yuuji@0
|
89 ret->s_addr = adr; /* set address */
|
yuuji@0
|
90 }
|
yuuji@0
|
91 return (void *) ret;
|
yuuji@0
|
92 }
|
yuuji@0
|
93
|
yuuji@0
|
94 /* Create a maximum-size socket address
|
yuuji@0
|
95 * Accepts: pointer to return maximum socket address length
|
yuuji@0
|
96 * Returns: new, empty socket address of maximum size
|
yuuji@0
|
97 */
|
yuuji@0
|
98
|
yuuji@0
|
99 struct sockaddr *ip_newsockaddr (size_t *len)
|
yuuji@0
|
100 {
|
yuuji@0
|
101 return (struct sockaddr *) memset (fs_get (SADRLEN),0,*len = SADRLEN);
|
yuuji@0
|
102 }
|
yuuji@0
|
103
|
yuuji@0
|
104
|
yuuji@0
|
105 /* Stuff a socket address
|
yuuji@0
|
106 * Accepts: address family
|
yuuji@0
|
107 * IPv4 address
|
yuuji@0
|
108 * length of address (always 4 in IPv4)
|
yuuji@0
|
109 * port number
|
yuuji@0
|
110 * pointer to return socket address length
|
yuuji@0
|
111 * Returns: socket address or NIL if error
|
yuuji@0
|
112 */
|
yuuji@0
|
113
|
yuuji@0
|
114 struct sockaddr *ip_sockaddr (int family,void *adr,size_t adrlen,
|
yuuji@0
|
115 unsigned short port,size_t *len)
|
yuuji@0
|
116 {
|
yuuji@0
|
117 struct sockaddr *sadr = ip_newsockaddr (len);
|
yuuji@0
|
118 switch (family) { /* build socket address based upon family */
|
yuuji@0
|
119 case AF_INET: /* IPv4 */
|
yuuji@0
|
120 sadr->sa_family = PF_INET;
|
yuuji@0
|
121 /* copy host address */
|
yuuji@0
|
122 memcpy (&SADR4ADR (sadr),adr,adrlen);
|
yuuji@0
|
123 /* copy port number in network format */
|
yuuji@0
|
124 SADR4PORT (sadr) = htons (port);
|
yuuji@0
|
125 *len = SADR4LEN;
|
yuuji@0
|
126 break;
|
yuuji@0
|
127 default: /* non-IP?? */
|
yuuji@0
|
128 sadr->sa_family = PF_UNSPEC;
|
yuuji@0
|
129 break;
|
yuuji@0
|
130 }
|
yuuji@0
|
131 return sadr;
|
yuuji@0
|
132 }
|
yuuji@0
|
133
|
yuuji@0
|
134 /* Return name from socket address
|
yuuji@0
|
135 * Accepts: socket address
|
yuuji@0
|
136 * Returns: canonical name for that address or NIL if none
|
yuuji@0
|
137 */
|
yuuji@0
|
138
|
yuuji@0
|
139 char *ip_sockaddrtoname (struct sockaddr *sadr)
|
yuuji@0
|
140 {
|
yuuji@0
|
141 struct hostent *he;
|
yuuji@0
|
142 return ((sadr->sa_family == PF_INET) &&
|
yuuji@0
|
143 (he = gethostbyaddr ((char *) &SADR4ADR (sadr),ADR4LEN,AF_INET))) ?
|
yuuji@0
|
144 (char *) he->h_name : NIL;
|
yuuji@0
|
145 }
|
yuuji@0
|
146
|
yuuji@0
|
147
|
yuuji@0
|
148 /* Return address from name
|
yuuji@0
|
149 * Accepts: name or NIL to return next address
|
yuuji@0
|
150 * pointer to previous/returned length
|
yuuji@0
|
151 * pointer to previous/returned address family
|
yuuji@0
|
152 * pointer to previous/returned canonical name
|
yuuji@0
|
153 * pointer to previous/return state for next-address calls
|
yuuji@0
|
154 * Returns: address with length/family/canonical updated if needed, or NIL
|
yuuji@0
|
155 */
|
yuuji@0
|
156
|
yuuji@0
|
157 void *ip_nametoaddr (char *name,size_t *len,int *family,char **canonical,
|
yuuji@0
|
158 void **next)
|
yuuji@0
|
159 {
|
yuuji@0
|
160 char **adl,tmp[MAILTMPLEN];
|
yuuji@0
|
161 struct hostent *he;
|
yuuji@0
|
162 if (name) { /* first lookup? */
|
yuuji@0
|
163 /* yes, do case-independent lookup */
|
yuuji@0
|
164 if ((strlen (name) < MAILTMPLEN) &&
|
yuuji@0
|
165 (he = gethostbyname (lcase (strcpy (tmp,name))))) {
|
yuuji@0
|
166 adl = he->h_addr_list;
|
yuuji@0
|
167 if (len) *len = he->h_length;
|
yuuji@0
|
168 if (family) *family = he->h_addrtype;
|
yuuji@0
|
169 if (canonical) *canonical = (char *) he->h_name;
|
yuuji@0
|
170 if (next) *next = (void *) adl;
|
yuuji@0
|
171 }
|
yuuji@0
|
172 else { /* error */
|
yuuji@0
|
173 adl = NIL;
|
yuuji@0
|
174 if (len) *len = 0;
|
yuuji@0
|
175 if (family) *family = 0;
|
yuuji@0
|
176 if (canonical) *canonical = NIL;
|
yuuji@0
|
177 if (next) *next = NIL;
|
yuuji@0
|
178 }
|
yuuji@0
|
179 }
|
yuuji@0
|
180 /* return next in series */
|
yuuji@0
|
181 else if (next && (adl = (char **) *next)) *next = ++adl;
|
yuuji@0
|
182 else adl = NIL; /* failure */
|
yuuji@0
|
183 return adl ? (void *) *adl : NIL;
|
yuuji@0
|
184 }
|