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