Annotation of libelwix/src/net.c, revision 1.5
1.1 misho 1: /*************************************************************************
2: * (C) 2013 AITNET ltd - Sofia/Bulgaria - <misho@aitnet.org>
3: * by Michael Pounov <misho@elwix.org>
4: *
5: * $Author: misho $
1.5 ! misho 6: * $Id: net.c,v 1.4.2.1 2013/06/10 14:49:48 misho Exp $
1.1 misho 7: *
8: **************************************************************************
9: The ELWIX and AITNET software is distributed under the following
10: terms:
11:
12: All of the documentation and software included in the ELWIX and AITNET
13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
14:
15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
16: by Michael Pounov <misho@elwix.org>. All rights reserved.
17:
18: Redistribution and use in source and binary forms, with or without
19: modification, are permitted provided that the following conditions
20: are met:
21: 1. Redistributions of source code must retain the above copyright
22: notice, this list of conditions and the following disclaimer.
23: 2. Redistributions in binary form must reproduce the above copyright
24: notice, this list of conditions and the following disclaimer in the
25: documentation and/or other materials provided with the distribution.
26: 3. All advertising materials mentioning features or use of this software
27: must display the following acknowledgement:
28: This product includes software developed by Michael Pounov <misho@elwix.org>
29: ELWIX - Embedded LightWeight unIX and its contributors.
30: 4. Neither the name of AITNET nor the names of its contributors
31: may be used to endorse or promote products derived from this software
32: without specific prior written permission.
33:
34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44: SUCH DAMAGE.
45: */
46: #include "global.h"
47:
48:
49: /*
50: * e_ether_ntoa() - Convert ethernet address to string
51: *
52: * @n = ethernet address structure, like struct ether_addr
53: * @a = string
54: * @len = string length
55: * return: NULL error or !=NULL string a
56: */
1.2 misho 57: char *
1.1 misho 58: e_ether_ntoa(const struct e_ether_addr *n, char * __restrict a, int len)
59: {
60: if (!n || !a)
61: return NULL;
62:
63: memset(a, 0, len);
64: if (snprintf(a, len, "%02x:%02x:%02x:%02x:%02x:%02x",
65: n->ether_addr_octet[0], n->ether_addr_octet[1],
66: n->ether_addr_octet[2], n->ether_addr_octet[3],
67: n->ether_addr_octet[4], n->ether_addr_octet[5]) < 17)
68: return NULL;
69:
70: return a;
71: }
72:
73: /*
74: * e_ether_aton() - Convert string to ethernet address
75: *
76: * @a = string
77: * @e = ethernet address structure, like struct ether_addr
78: * return: NULL error or !=NULL ethernet address structure
79: */
1.2 misho 80: struct e_ether_addr *
1.1 misho 81: e_ether_aton(const char *a, struct e_ether_addr *e)
82: {
83: int i;
84: u_int o0, o1, o2, o3, o4, o5;
85:
86: if (!a || !e)
87: return NULL;
88:
89: i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5);
90: if (i != 6)
91: return NULL;
92:
93: e->ether_addr_octet[0] = o0;
94: e->ether_addr_octet[1] = o1;
95: e->ether_addr_octet[2] = o2;
96: e->ether_addr_octet[3] = o3;
97: e->ether_addr_octet[4] = o4;
98: e->ether_addr_octet[5] = o5;
99:
100: return e;
101: }
102:
103: /*
104: * e_n2port() - Extract port from network structure
105: *
106: * @addr = Address
107: * return: 0 not supported family type or port number
108: */
1.2 misho 109: u_short
1.1 misho 110: e_n2port(sockaddr_t * __restrict addr)
111: {
112: u_short port = 0;
113:
114: if (!addr)
115: return port;
116:
117: switch (addr->sa.sa_family) {
118: case AF_INET:
119: return ntohs(addr->sin.sin_port);
120: case AF_INET6:
121: return ntohs(addr->sin6.sin6_port);
122: default:
123: break;
124: }
125:
126: return port;
127: }
128:
129: /*
130: * e_n2addr() - Extract address from network structure
131: *
132: * @addr = Address
133: * @val = Value for store string address
134: * return: NULL error or !=NULL string address from val
135: */
136: const char *
137: e_n2addr(sockaddr_t * __restrict addr, ait_val_t * __restrict val)
138: {
1.5 ! misho 139: char *s, str[INET6_ADDRSTRLEN] = { 0 };
1.1 misho 140: const char *ret = NULL;
141:
142: if (!addr || !val)
143: return ret;
144:
145: AIT_INIT_VAL(val);
146: switch (addr->sa.sa_family) {
147: case AF_INET:
148: if (!inet_ntop(AF_INET, &addr->sin.sin_addr, str, INET_ADDRSTRLEN)) {
149: LOGERR;
150: return ret;
151: } else
152: ret = str;
153: break;
154: case AF_INET6:
155: if (!inet_ntop(AF_INET6, &addr->sin6.sin6_addr, str, INET6_ADDRSTRLEN)) {
156: LOGERR;
157: return ret;
158: } else
159: ret = str;
160: break;
161: case AF_LOCAL:
162: ret = addr->sun.sun_path;
163: break;
1.5 ! misho 164: case AF_LINK:
! 165: if (!(s = link_ntoa(&addr->sdl))) {
! 166: LOGERR;
! 167: return ret;
! 168: } else
! 169: ret = s;
! 170: break;
1.1 misho 171: default:
172: elwix_SetErr(EPROTONOSUPPORT, "Unsuported address family %d",
173: addr->sa.sa_family);
174: return ret;
175: }
176:
177: AIT_SET_STR(val, ret);
178: return (const char*) AIT_GET_STR(val);
179: }
180:
181: /*
182: * e_gethostbyname() - Get host and port and make network structure
183: *
184: * @psHost = Hostname
185: * @port = Port
186: * @addr = Network address structure
187: * return: NULL error or !=NULL network structure
188: */
189: sockaddr_t *
190: e_gethostbyname(const char *psHost, u_short port, sockaddr_t * __restrict addr)
191: {
192: struct hostent *host = NULL;
193:
194: if (!psHost || !addr)
195: return NULL;
196:
197: if (*psHost != '/') {
198: /* resolver */
199: if (!addr->sa.sa_family)
200: host = gethostbyname(psHost);
201: else
202: host = gethostbyname2(psHost, addr->sa.sa_family);
203: if (!host) {
204: elwix_SetErr(EINVAL, "Resolver #%d - %s", h_errno, hstrerror(h_errno));
205: return NULL;
206: } else {
207: memset(addr, 0, sizeof(sockaddr_t));
208: addr->sa.sa_family = host->h_addrtype;
209: }
210: } else {
211: memset(addr, 0, sizeof(sockaddr_t));
212: addr->sa.sa_family = AF_LOCAL;
213: }
214:
215:
216: switch (addr->sa.sa_family) {
217: case AF_INET:
218: addr->sin.sin_len = sizeof(struct sockaddr_in);
219: addr->sin.sin_family = AF_INET;
220: addr->sin.sin_port = htons(port);
221: memcpy(&addr->sin.sin_addr, host->h_addr, sizeof addr->sin.sin_addr);
222: return addr;
223: case AF_INET6:
224: addr->sin6.sin6_len = sizeof(struct sockaddr_in6);
225: addr->sin6.sin6_family = AF_INET6;
226: addr->sin6.sin6_port = htons(port);
227: memcpy(&addr->sin6.sin6_addr, host->h_addr, sizeof addr->sin6.sin6_addr);
228: return addr;
229: case AF_LOCAL:
230: addr->sun.sun_len = sizeof(struct sockaddr_un);
231: addr->sun.sun_family = AF_LOCAL;
232: memset(addr->sun.sun_path, 0, sizeof addr->sun.sun_path);
233: snprintf(addr->sun.sun_path, sizeof addr->sun.sun_path, "%s-%hu", psHost, port);
234: return addr;
235: default:
236: elwix_SetErr(EPROTONOSUPPORT, "Unsuported address family %d", addr->sa.sa_family);
237: break;
238: }
239:
240: return NULL;
241: }
242:
243: /*
244: * e_addrcmp() - Compare network addresses
245: *
246: * @a = 1st address
247: * @b = 2nd address
248: * @p = compare and ports, if family is AF_INET or AF_INET6
249: * return: 0 is equal or !=0 is different
250: */
251: int
252: e_addrcmp(sockaddr_t * __restrict a, sockaddr_t * __restrict b, int p)
253: {
254: if (a && b && a->sa.sa_family == b->sa.sa_family)
255: switch (a->sa.sa_family) {
256: case AF_LOCAL:
257: return strcmp(a->sun.sun_path, b->sun.sun_path);
258: case AF_INET:
259: if (p && (a->sin.sin_port - b->sin.sin_port))
260: return (int) !!(a->sin.sin_port - b->sin.sin_port);
261: else
262: return memcmp(&a->sin.sin_addr, &b->sin.sin_addr,
263: sizeof a->sin.sin_addr);
264: case AF_INET6:
265: if (p && (a->sin6.sin6_port - b->sin6.sin6_port))
266: return (int) !!(a->sin6.sin6_port - b->sin6.sin6_port);
267: else
268: return memcmp(&a->sin6.sin6_addr, &b->sin6.sin6_addr,
269: sizeof a->sin6.sin6_addr);
270: case AF_LINK:
271: return memcmp(&a->sdl.sdl_data, &b->sdl.sdl_data,
272: sizeof a->sdl.sdl_data);
273: }
274:
275: return (int) !!(a - b);
276: }
277:
278: /*
279: * e_usleep() - usleep() replacement for ELWIX
280: *
281: * @usec = microseconds for sleep
282: * return: -1 interrupted by signal or 0 ok
283: */
1.2 misho 284: int
1.1 misho 285: e_usleep(u_int usec)
286: {
287: struct timeval tv = { (time_t) (usec / 1000000), (long) (usec % 1000000) };
288:
289: return select(0, NULL, NULL, NULL, &tv);
290: }
1.3 misho 291:
292: /*
293: * e_innet() - Test address match in network
294: *
295: * @net = network
296: * @addr = address
297: * return: -1 error, 0 match or 1 not match
298: */
299: int
300: e_innet(netaddr_t * __restrict net, inaddr_t * __restrict addr)
301: {
302: register int i;
303: int ret = 0;
304:
305: if (!net || !addr)
306: return -1;
307:
308: switch (net->addr.sa.sa_family) {
309: case AF_INET:
310: for (i = 0; i < sizeof(struct in_addr); i++) {
311: ret = ((caddr_t) &net->addr.sin.sin_addr.s_addr)[i] &
312: net->mask.in.s4_addr[i];
313: ret -= addr->in.s4_addr[i] & net->mask.in.s4_addr[i];
314: if (ret)
315: break;
316: }
317: break;
318: case AF_INET6:
319: for (i = 0; i < sizeof(struct in6_addr); i++) {
320: ret = net->addr.sin6.sin6_addr.s6_addr[i] &
321: net->mask.in6.s6_addr[i];
322: ret -= addr->in6.s6_addr[i] & net->mask.in6.s6_addr[i];
323: if (ret)
324: break;
325: }
326: break;
327: default:
328: return -1;
329: }
330:
331: return !!ret;
332: }
1.4 misho 333:
334: /*
335: * e_getnet() - Get network from string
336: *
337: * @net = Network string (format: <net[/cidr]>)
338: * return: NULL error or !=NULL network should be e_free()
339: */
340: netaddr_t *
341: e_getnet(const char *net)
342: {
343: netaddr_t *n;
344: char *str, *wrk;
345: struct hostent *host;
346:
347: n = e_malloc(sizeof(netaddr_t));
348: if (!n) {
349: LOGERR;
350: return NULL;
351: } else
352: memset(n, 0, sizeof(netaddr_t));
353: str = e_strdup(net);
354: if (!str) {
355: LOGERR;
356: e_free(n);
357: return NULL;
358: }
359: wrk = strchr(str, '/');
360: if (wrk)
361: *wrk++ = 0;
362:
363: host = gethostbyname2(str, strchr(str, ':') ? AF_INET6 : AF_INET);
364: if (!host) {
365: elwix_SetErr(EINVAL, "Resolver #%d - %s", h_errno, hstrerror(h_errno));
366: e_free(str);
367: e_free(n);
368: return NULL;
369: }
370: switch (host->h_addrtype) {
371: case AF_INET:
372: n->addr.sin.sin_len = sizeof(struct sockaddr_in);
373: n->addr.sin.sin_family = host->h_addrtype;
374: memcpy(&n->addr.sin.sin_addr, host->h_addr, sizeof n->addr.sin.sin_addr);
375: if (wrk)
376: n->mask.in.s_addr = E_CIDRMASK(strtol(wrk, NULL, 10));
377: else
378: n->mask.in.s_addr = 0xFFFFFFFF;
379: break;
380: case AF_INET6:
381: n->addr.sin6.sin6_len = sizeof(struct sockaddr_in6);
382: n->addr.sin6.sin6_family = host->h_addrtype;
383: memcpy(&n->addr.sin6.sin6_addr, host->h_addr, sizeof n->addr.sin6.sin6_addr);
384: /* TODO: should support ipv6 mask */
385: break;
386: default:
387: elwix_SetErr(EINVAL, "Unsupported family #%d", host->h_addrtype);
388: e_free(str);
389: e_free(n);
390: return NULL;
391: }
392:
393: e_free(str);
394: return n;
395: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>