1 #define _BSD_SOURCE
2 #include<netdb.h>
3 #include<stdio.h>
4 #include<stdlib.h>
5 #include<string.h>
6 #include<arpa/inet.h>
7 #include<errno.h>
8
9 #define HOST_FILE_PATH "/etc/hosts"
10 #define NET_FILE_PATH "/etc/networks"
11 #define BUFFER_SIZE 200
12 #define INET_ADDR_LEN 4
13 #define INET6_ADDR_LEN 16
14 #define MAX_ALIAS_NO 10
15 #define MAX_ADDR_NO 10
16 #define MAX_NAME_LEN 20
17 #define MAX_ALIAS_LEN 20
18
19 struct hostdata {
20 FILE *hostf;
21 int stayopen;
22 struct hostent he;
23 char buf[BUFFER_SIZE];
24 char *addr[MAX_ADDR_NO + 1];
25 char addr_list[MAX_ADDR_NO + 1][INET6_ADDR_LEN + 1];
26 char *aliases[MAX_ALIAS_NO + 1];
27 };
28
29 struct netdata {
30 FILE *netf;
31 int stayopen;
32 struct netent ne;
33 char buf[BUFFER_SIZE];
34 char *aliases[MAX_ALIAS_NO + 1];
35 };
36
37 static struct hostdata *hd = NULL;
38 static struct netdata *nd = NULL;
39
gethostent_resolv()40 static int gethostent_resolv()
41 {
42 char *ch, *ptr = NULL;
43 if (hd->buf[0] == '#')
44 return -1;
45
46 ch = strchr(hd->buf, '#');
47 if (ch)
48 *ch = '\0';
49 ch = strtok_r(hd->buf, " \t\n", &ptr);
50 if (!ch)
51 return -1;
52
53 if (inet_pton(AF_INET, ch, hd->addr_list[0]) == 1) {
54 hd->he.h_addrtype = AF_INET;
55 hd->he.h_length = INET_ADDR_LEN;
56 hd->addr_list[0][INET_ADDR_LEN] = '\0';
57 } else if (inet_pton(AF_INET6, ch, hd->addr_list[0]) == 1) {
58 hd->he.h_addrtype = AF_INET6;
59 hd->he.h_length = INET6_ADDR_LEN;
60 hd->addr_list[0][INET6_ADDR_LEN] = '\0';
61 } else {
62 return -1;
63 }
64
65 hd->addr[0] = hd->addr_list[0];
66 hd->addr[1] = NULL;
67 hd->he.h_addr_list = hd->addr;
68
69 ch = strtok_r(NULL, " \t\n", &ptr);
70 if (!ch)
71 return -1;
72 hd->he.h_name = ch;
73
74 int i = 0;
75 while (i < MAX_ALIAS_NO) {
76 ch = strtok_r(NULL, " \t\n", &ptr);
77 hd->aliases[i++] = ch;
78 }
79
80 hd->aliases[MAX_ALIAS_NO] = NULL;
81 hd->he.h_aliases = hd->aliases;
82 return 0;
83 }
84
gethostent(void)85 struct hostent *gethostent(void)
86 {
87 if (hd == NULL) {
88 if ((hd = malloc(sizeof(struct hostdata))) == NULL) {
89 h_errno = NO_RECOVERY;
90 return NULL;
91 }
92 hd->hostf = NULL;
93 hd->stayopen = 0;
94 }
95 if (!hd->hostf && !(hd->hostf = fopen(HOST_FILE_PATH, "r"))) {
96 h_errno = NO_RECOVERY;
97 free(hd);
98 hd =NULL;
99 return NULL;
100 }
101 do {
102 if (!fgets(hd->buf, BUFFER_SIZE, hd->hostf)) {
103 h_errno = HOST_NOT_FOUND;
104 return NULL;
105 }
106 } while (gethostent_resolv());
107
108 return &(hd->he);
109 }
110
sethostent(int stayopen)111 void sethostent(int stayopen)
112 {
113 if (hd == NULL) {
114 if ((hd = malloc(sizeof(struct hostdata))) == NULL) {
115 h_errno = NO_RECOVERY;
116 return;
117 }
118 hd->hostf = NULL;
119 }
120 if (hd->hostf == NULL)
121 hd->hostf = fopen(NET_FILE_PATH, "r");
122 else
123 rewind(hd->hostf);
124 hd->stayopen = stayopen;
125 }
126
endhostent(void)127 void endhostent(void)
128 {
129 if (hd == NULL)
130 return;
131 if (hd->stayopen == 0) {
132 if (hd->hostf != NULL)
133 fclose(hd->hostf);
134 free(hd);
135 hd = NULL;
136 }
137 }
138
getnetent_resolv()139 static int getnetent_resolv()
140 {
141 if (nd->buf[0] == '#')
142 return -1;
143 char *ch, *ptr = NULL;
144 ch = strchr(nd->buf, '#');
145 if (ch)
146 *ch = '\0';
147 ch = strtok_r(nd->buf, " \t\n", &ptr);
148 if (!ch)
149 return -1;
150 nd->ne.n_name = ch;
151 nd->ne.n_addrtype = AF_INET;
152
153 ch = strtok_r(NULL, " \t\n", &ptr);
154 if (!ch)
155 return -1;
156 nd->ne.n_net = inet_network(ch);
157
158 int i = 0;
159 while ((ch = strtok_r(NULL, " \t\n", &ptr)) != NULL && i < MAX_ALIAS_NO) {
160 nd->aliases[i++] = ch;
161 }
162 nd->aliases[i] = NULL;
163 nd->ne.n_aliases = nd->aliases;
164 return 0;
165 }
166
getnetent(void)167 struct netent *getnetent(void)
168 {
169 if (nd == NULL) {
170 if ((nd = malloc(sizeof(struct netdata))) == NULL) {
171 errno = ENOMEM;
172 return NULL;
173 }
174 nd->netf = NULL;
175 nd->stayopen = 0;
176 }
177 if (nd->netf == NULL && (nd->netf = fopen(NET_FILE_PATH, "r")) == NULL) {
178 errno = ENOENT;
179 free(nd);
180 nd = NULL;
181 return NULL;
182 }
183 while (1) {
184 if (fgets(nd->buf, BUFFER_SIZE, nd->netf) == NULL)
185 break;
186 if (getnetent_resolv() == 0)
187 return &(nd->ne);
188 }
189
190 return NULL;
191 }
192
setnetent(int stayopen)193 void setnetent(int stayopen)
194 {
195 if (nd == NULL) {
196 if ((nd = malloc(sizeof(struct netdata))) == NULL) {
197 errno = ENOMEM;
198 return;
199 }
200 nd->netf = NULL;
201 }
202 if (nd->netf == NULL)
203 nd->netf = fopen(NET_FILE_PATH, "r");
204 else
205 rewind(nd->netf);
206 nd->stayopen = stayopen;
207 }
208
endnetent(void)209 void endnetent(void)
210 {
211 if (nd == NULL)
212 return;
213 if (!nd->stayopen) {
214 if (nd->netf != NULL)
215 fclose(nd->netf);
216 free(nd);
217 nd = NULL;
218 }
219 }