1 /* This file is part of Netwib. Read and honor its license.
2 */
3
4 /*-------------------------------------------------------------*/
5 #if defined NETWIBDEF_SYSNAME_Linux
6 #define NETWIB_IPINITETH_IOCTLRARP 1
netwib_priv_ip_init_eth_ioctlrarp(netwib_consteth * peth,netwib_ip * pip)7 static netwib_err netwib_priv_ip_init_eth_ioctlrarp(netwib_consteth *peth,
8 netwib_ip *pip)
9 {
10 netwib_byte *pb;
11 netwib_ip4 ip4;
12 struct arpreq ar;
13 int fd, reti;
14
15 netwib_c_memset(&ar, 0, sizeof(ar));
16 ar.arp_pa.sa_family = AF_INET;
17 netwib_c_memcpy(ar.arp_ha.sa_data, peth->b, NETWIB_ETH_LEN);
18
19 fd = socket(AF_INET, SOCK_DGRAM, 0);
20 if (fd == -1) {
21 return(NETWIB_ERR_FUSOCKET);
22 }
23
24 reti = ioctl(fd, SIOCGRARP, (char *)&ar);
25 close(fd);
26 if (reti == -1) {
27 if (errno == EINVAL || errno == ENXIO) {
28 /* RARP is not supported by kernel */
29 return(NETWIB_ERR_NOTCONVERTED);
30 }
31 return(NETWIB_ERR_FUIOCTL);
32 }
33
34 pb = (netwib_data) (ar.arp_pa.sa_data + 2);
35 ip4 = (*pb++) << 24;
36 ip4 |= (*pb++) << 16;
37 ip4 |= (*pb++) << 8;
38 ip4 |= *pb;
39 if (ip4 == 0) {
40 /* SuSE 5.1 indicates a 0 IP address instead of returning an error
41 in ioctl(fd, SIOCGRARP, ...) */
42 return(NETWIB_ERR_NOTCONVERTED);
43 }
44 if (pip != NULL) {
45 pip->iptype = NETWIB_IPTYPE_IP4;
46 pip->ipvalue.ip4 = ip4;
47 }
48
49 return(NETWIB_ERR_OK);
50 }
51 #else
52 #define NETWIB_IPINITETH_IOCTLRARP 0
53 #endif
54
55 /*-------------------------------------------------------------*/
56 #if NETWIBDEF_HAVEFUNC_ETHER_NTOHOST==1
57 #define NETWIB_IPINITETH_ETCETHERS 1
netwib_priv_ip_init_eth_etcethers(netwib_consteth * peth,netwib_ip * pip)58 static netwib_err netwib_priv_ip_init_eth_etcethers(netwib_consteth *peth,
59 netwib_ip *pip)
60 {
61 netwib_char array[1024];
62 netwib_err ret;
63 struct ether_addr ea;
64 int reti;
65
66 #if defined NETWIBDEF_SYSNAME_FreeBSD || defined NETWIBDEF_SYSNAME_MacOS
67 netwib_c_memcpy(ea.octet, peth->b, NETWIB_ETH_LEN);
68 #else
69 netwib_c_memcpy(ea.ether_addr_octet, peth->b, NETWIB_ETH_LEN);
70 #endif
71 reti = ether_ntohost(array, &ea);
72 if (reti) {
73 return(NETWIB_ERR_NOTCONVERTED);
74 }
75
76 ret = netwib_priv_ip_init_sip4(array, pip);
77 if (ret == NETWIB_ERR_OK) return(NETWIB_ERR_OK);
78
79 /* because the function can return a hostname */
80 netwib_er(netwib_priv_ip_init_hn4(array, pip));
81
82 return(NETWIB_ERR_OK);
83 }
84 #else
85 #define NETWIB_IPINITETH_ETCETHERS 0
86 #endif
87
88 /*-------------------------------------------------------------*/
netwib_ip_init_eth2(netwib_consteth * peth,netwib_ip * pip)89 static netwib_err netwib_ip_init_eth2(netwib_consteth *peth,
90 netwib_ip *pip)
91 {
92 netwib_err ret = NETWIB_ERR_NOTCONVERTED;
93
94 #if NETWIB_IPINITETH_IOCTLRARP == 1
95 ret = netwib_priv_ip_init_eth_ioctlrarp(peth, pip);
96 if (ret == NETWIB_ERR_OK) return(NETWIB_ERR_OK);
97 if (ret != NETWIB_ERR_NOTCONVERTED) return(ret);
98 #endif
99
100 #if NETWIB_IPINITETH_ETCETHERS == 1
101 ret = netwib_priv_ip_init_eth_etcethers(peth, pip);
102 if (ret == NETWIB_ERR_OK) return(NETWIB_ERR_OK);
103 if (ret != NETWIB_ERR_NOTCONVERTED) return(ret);
104 #endif
105
106 ret = netwib_priv_confrel_arpcache_ip(peth, pip);
107 if (ret == NETWIB_ERR_OK) return(NETWIB_ERR_OK);
108 if (ret != NETWIB_ERR_NOTCONVERTED) return(ret);
109
110 /* we could also send an RARP request, but nowadays, nobody answers */
111
112 return(ret);
113 }
114
115 /*-------------------------------------------------------------*/
netwib_ip_init_eth(netwib_consteth * peth,netwib_ip * pip)116 netwib_err netwib_ip_init_eth(netwib_consteth *peth,
117 netwib_ip *pip)
118 {
119 netwib_ip ipa;
120 netwib_err ret;
121
122 ret = netwib_priv_confglo_arpcache_ip(peth, pip);
123 if (ret == NETWIB_ERR_NOTCONVERTED) {
124 ret = netwib_ip_init_eth2(peth, &ipa);
125 if (ret == NETWIB_ERR_OK) {
126 /* add value in ARP cache */
127 netwib_er(netwib_priv_confglo_arpcache_add(NULL, peth, pip));
128 if (pip != NULL) *pip = ipa;
129 }
130 }
131 return(ret);
132 }
133