• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }