enable -fno-strict-aliasing until the code base gets a hefty clean up to fix all...
[platform/upstream/net-tools.git] / lib / ether.c
1 /*
2  * lib/ether.c        This file contains an implementation of the "Ethernet"
3  *              support functions.
4  *
5  * Version:     $Id: ether.c,v 1.8 2002/07/30 05:17:29 ecki Exp $
6  *
7  * Author:      Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
8  *              Copyright 1993 MicroWalt Corporation
9  *
10  *              This program is free software; you can redistribute it
11  *              and/or  modify it under  the terms of  the GNU General
12  *              Public  License as  published  by  the  Free  Software
13  *              Foundation;  either  version 2 of the License, or  (at
14  *              your option) any later version.
15  */
16 #include "config.h"
17
18 #if HAVE_HWETHER
19 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <net/if_arp.h>
22 #include <linux/if_ether.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <errno.h>
26 #include <ctype.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include "net-support.h"
30 #include "pathnames.h"
31 #include "intl.h"
32 #include "util.h"
33
34 extern struct hwtype ether_hwtype;
35
36
37 /* Display an Ethernet address in readable format. */
38 static char *pr_ether(unsigned char *ptr)
39 {
40     static char buff[64];
41
42     snprintf(buff, sizeof(buff), "%02x:%02x:%02x:%02x:%02x:%02x",
43              (ptr[0] & 0377), (ptr[1] & 0377), (ptr[2] & 0377),
44              (ptr[3] & 0377), (ptr[4] & 0377), (ptr[5] & 0377)
45         );
46     return (buff);
47 }
48
49
50 /* Input an Ethernet address and convert to binary. */
51 static int in_ether(char *bufp, struct sockaddr *sap)
52 {
53     unsigned char *ptr;
54     char c, *orig;
55     int i;
56     unsigned val;
57
58     sap->sa_family = ether_hwtype.type;
59     ptr = sap->sa_data;
60
61     i = 0;
62     orig = bufp;
63     while ((*bufp != '\0') && (i < ETH_ALEN)) {
64         val = 0;
65         c = *bufp++;
66         if (isdigit(c))
67             val = c - '0';
68         else if (c >= 'a' && c <= 'f')
69             val = c - 'a' + 10;
70         else if (c >= 'A' && c <= 'F')
71             val = c - 'A' + 10;
72         else {
73 #ifdef DEBUG
74             fprintf(stderr, _("in_ether(%s): invalid ether address!\n"), orig);
75 #endif
76             errno = EINVAL;
77             return (-1);
78         }
79         val <<= 4;
80         c = *bufp;
81         if (isdigit(c))
82             val |= c - '0';
83         else if (c >= 'a' && c <= 'f')
84             val |= c - 'a' + 10;
85         else if (c >= 'A' && c <= 'F')
86             val |= c - 'A' + 10;
87         else if (c == ':' || c == 0)
88             val >>= 4;
89         else {
90 #ifdef DEBUG
91             fprintf(stderr, _("in_ether(%s): invalid ether address!\n"), orig);
92 #endif
93             errno = EINVAL;
94             return (-1);
95         }
96         if (c != 0)
97             bufp++;
98         *ptr++ = (unsigned char) (val & 0377);
99         i++;
100
101         /* We might get a semicolon here - not required. */
102         if (*bufp == ':') {
103             if (i == ETH_ALEN) {
104 #ifdef DEBUG
105                 fprintf(stderr, _("in_ether(%s): trailing : ignored!\n"),
106                         orig)
107 #endif
108                     ;           /* nothing */
109             }
110             bufp++;
111         }
112     }
113
114     /* That's it.  Any trailing junk? */
115     if ((i == ETH_ALEN) && (*bufp != '\0')) {
116 #ifdef DEBUG
117         fprintf(stderr, _("in_ether(%s): trailing junk!\n"), orig);
118         errno = EINVAL;
119         return (-1);
120 #endif
121     }
122 #ifdef DEBUG
123     fprintf(stderr, "in_ether(%s): %s\n", orig, pr_ether(sap->sa_data));
124 #endif
125
126     return (0);
127 }
128
129
130 struct hwtype ether_hwtype =
131 {
132     "ether", NULL, /*"10Mbps Ethernet", */ ARPHRD_ETHER, ETH_ALEN,
133     pr_ether, in_ether, NULL
134 };
135
136
137 #endif                          /* HAVE_HWETHER */