1 /*
2                                   NETWIB
3                              Network library
4                 Copyright(c) 1999-2010 Laurent Constantin
5                                   -----
6 
7   Main server   : http://www.laurentconstantin.com/
8   Backup server : http://laurentconstantin.free.fr/
9   [my current email address is on the web servers]
10 
11                                   -----
12   This file is part of Netwib.
13 
14   Netwib is free software: you can redistribute it and/or modify
15   it under the terms of the GNU General Public License version 3
16   as published by the Free Software Foundation.
17 
18   Netwib is distributed in the hope that it will be useful,
19   but WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21   GNU General Public License for more details (http://www.gnu.org/).
22 
23 ------------------------------------------------------------------------
24 */
25 
26 #include <netwib/inc/maininc.h>
27 
28 /*-------------------------------------------------------------*/
netwib_ports_init(netwib_ports_inittype inittype,netwib_ports ** ppports)29 netwib_err netwib_ports_init(netwib_ports_inittype inittype,
30                              netwib_ports **ppports)
31 {
32   netwib_ports *pports;
33   netwib_err ret;
34 
35   /* parameter verification */
36   if (ppports == NULL) {
37     return(NETWIB_ERR_PANULLPTR);
38   }
39 
40   /* allocate needed memory to store pports */
41   netwib_er(netwib_ptr_malloc(sizeof(netwib_ports), (netwib_ptr*)&pports));
42   *ppports = pports;
43 
44   ret = netwib_priv_ranges_init(inittype, NETWIB_PORT_LEN, &pports->ranges);
45   if (ret != NETWIB_ERR_OK) {
46     netwib_er(netwib_ptr_free((netwib_ptr*)&pports));
47     return(ret);
48   }
49 
50 #if NETWIB_DEBUG_LEAK==1
51   netwib_er(netwib_debug_leak_add_ports(pports));
52 #endif
53 
54   return(NETWIB_ERR_OK);
55 }
56 
57 /*-------------------------------------------------------------*/
netwib_ports_close(netwib_ports ** ppports)58 netwib_err netwib_ports_close(netwib_ports **ppports)
59 {
60   netwib_ports *pports;
61 
62   /* parameter verification */
63   if (ppports == NULL) {
64     return(NETWIB_ERR_PANULLPTR);
65   }
66   pports = *ppports;
67 
68   /* remove items */
69   netwib_er(netwib_priv_ranges_close(&pports->ranges));
70 
71 #if NETWIB_DEBUG_LEAK==1
72   netwib_er(netwib_debug_leak_del_ports(pports));
73 #endif
74 
75   /* free memory */
76   netwib_er(netwib_ptr_free((netwib_ptr*)&pports));
77 
78   return(NETWIB_ERR_OK);
79 }
80 
81 /*-------------------------------------------------------------*/
netwib_ports_add_port(netwib_ports * pports,netwib_port port)82 netwib_err netwib_ports_add_port(netwib_ports *pports,
83                                  netwib_port port)
84 {
85   netwib_byte portarray[NETWIB_PORT_LEN];
86 
87   /* parameter verification */
88   if (pports == NULL) {
89     return(NETWIB_ERR_PANULLPTR);
90   }
91 #if NETWIB_DEBUG_LEAK==1
92   netwib_er(netwib_debug_leak_valid_ports(pports));
93 #endif
94 
95   /* add item */
96   portarray[0] = netwib_c2_uint16_0(port);
97   portarray[1] = netwib_c2_uint16_1(port);
98   netwib_er(netwib_priv_ranges_add(&pports->ranges, portarray));
99 
100   return(NETWIB_ERR_OK);
101 }
102 
103 /*-------------------------------------------------------------*/
netwib_ports_add_portrange(netwib_ports * pports,netwib_port infport,netwib_port support)104 netwib_err netwib_ports_add_portrange(netwib_ports *pports,
105                                       netwib_port infport,
106                                       netwib_port support)
107 {
108   netwib_byte infportarray[NETWIB_PORT_LEN], supportarray[NETWIB_PORT_LEN];
109 
110   /* parameter verification */
111   if (pports == NULL) {
112     return(NETWIB_ERR_PANULLPTR);
113   }
114 #if NETWIB_DEBUG_LEAK==1
115   netwib_er(netwib_debug_leak_valid_ports(pports));
116 #endif
117 
118   /* add item */
119   infportarray[0] = netwib_c2_uint16_0(infport);
120   infportarray[1] = netwib_c2_uint16_1(infport);
121   supportarray[0] = netwib_c2_uint16_0(support);
122   supportarray[1] = netwib_c2_uint16_1(support);
123   netwib_er(netwib_priv_ranges_add_range(&pports->ranges, infportarray,
124                                          supportarray));
125 
126   return(NETWIB_ERR_OK);
127 }
128 
129 /*-------------------------------------------------------------*/
netwib_ports_add_ports(netwib_ports * pports,netwib_constports * pportstoadd)130 netwib_err netwib_ports_add_ports(netwib_ports *pports,
131                                   netwib_constports *pportstoadd)
132 {
133   netwib_priv_ranges_index rangesindex;
134   netwib_byte infportarray[NETWIB_PORT_LEN], supportarray[NETWIB_PORT_LEN];
135   netwib_err ret;
136 
137   /* parameter verification */
138   if (pports == NULL) {
139     return(NETWIB_ERR_PANULLPTR);
140   }
141 #if NETWIB_DEBUG_LEAK==1
142   netwib_er(netwib_debug_leak_valid_ports(pports));
143   netwib_er(netwib_debug_leak_valid_ports(pportstoadd));
144 #endif
145 
146   netwib_er(netwib_priv_ranges_index_init(&pportstoadd->ranges, &rangesindex));
147   ret = NETWIB_ERR_OK;
148   while(NETWIB_TRUE) {
149     ret = netwib_priv_ranges_index_next_range(&rangesindex, infportarray,
150                                              supportarray);
151     if (ret != NETWIB_ERR_OK) {
152       if (ret == NETWIB_ERR_DATAEND) ret = NETWIB_ERR_OK;
153       break;
154     }
155     netwib_er(netwib_priv_ranges_add_range(&pports->ranges, infportarray,
156                                          supportarray));
157   }
158   netwib_er(netwib_priv_ranges_index_close(&rangesindex));
159 
160   return(ret);
161 }
162 
163 /*-------------------------------------------------------------*/
netwib_priv_ports_add_buf(netwib_conststring str,netwib_data array,netwib_priv_ranges_separator * pseparator)164 static netwib_err netwib_priv_ports_add_buf(netwib_conststring str,
165                                             netwib_data array,
166                                             netwib_priv_ranges_separator
167                                             *pseparator)
168 {
169   netwib_conststring pc;
170   netwib_uint32 infport, support, numdigitfound, *pport;
171   netwib_priv_ranges_separator separator;
172   netwib_char c;
173 
174   pc = str;
175   numdigitfound = 0;
176   separator = NETWIB_PRIV_RANGES_SEPARATOR_NONE;
177   infport = 0;
178   support = 0;
179   pport = &infport;
180   while(NETWIB_TRUE) {
181     c = *pc;
182     if (c == '\0') {
183       if (numdigitfound == 0) return(NETWIB_ERR_NOTCONVERTED);
184       break;
185     } else if (c == '-') {
186       if (separator == NETWIB_PRIV_RANGES_SEPARATOR_DASH) {
187         return(NETWIB_ERR_NOTCONVERTED); /* forbid two separators */
188       }
189       separator = NETWIB_PRIV_RANGES_SEPARATOR_DASH;
190       numdigitfound = 0;
191       pport = &support;
192     } else if (netwib_c2_isdigit(c)) {
193       if (numdigitfound == 5) return(NETWIB_ERR_NOTCONVERTED);
194       numdigitfound++;
195       *pport = 10*(*pport) + netwib_c2_cto9(c);
196       if (*pport > 0xFFFF) return(NETWIB_ERR_NOTCONVERTED);
197     } else {
198       return(NETWIB_ERR_NOTCONVERTED);
199     }
200     pc++;
201   }
202 
203   array[0] = netwib_c2_uint16_0(infport);
204   array[1] = netwib_c2_uint16_1(infport);
205   *pseparator = separator;
206   if (separator == NETWIB_PRIV_RANGES_SEPARATOR_DASH) {
207     if (infport > support) return(NETWIB_ERR_NOTCONVERTED);
208     array[2] = netwib_c2_uint16_0(support);
209     array[3] = netwib_c2_uint16_1(support);
210   }
211 
212   return(NETWIB_ERR_OK);
213 }
214 
215 /*-------------------------------------------------------------*/
netwib_ports_add_buf(netwib_ports * pports,netwib_constbuf * pbuf)216 netwib_err netwib_ports_add_buf(netwib_ports *pports,
217                                 netwib_constbuf *pbuf)
218 {
219   netwib_err ret;
220 
221   ret = netwib_priv_ranges_add_buf(&pports->ranges, pbuf,
222                                    &netwib_priv_ports_add_buf);
223   if (ret != NETWIB_ERR_OK) {
224     netwib_er(netwib_priv_errmsg_string("bad port list: "));
225     netwib_er(netwib_priv_errmsg_append_buf(pbuf));
226   }
227   return(ret);
228 }
229 
230 /*-------------------------------------------------------------*/
netwib_ports_add_kbd(netwib_ports * pports,netwib_constbuf * pmessage,netwib_constbuf * pdefaultlist)231 netwib_err netwib_ports_add_kbd(netwib_ports *pports,
232                                 netwib_constbuf *pmessage,
233                                 netwib_constbuf *pdefaultlist)
234 {
235   netwib_buf buf;
236   netwib_ports *plocalports;
237   netwib_char prompt;
238   netwib_err ret;
239 
240   netwib_er(netwib_ports_init(pports->ranges.inittype, &plocalports));
241   if (pdefaultlist != NULL) {
242     ret = netwib_ports_add_buf(plocalports, pdefaultlist);
243     if (ret != NETWIB_ERR_OK) {
244       netwib_er(netwib_ports_close(&plocalports));
245       return(ret);
246     }
247     netwib_er(netwib_priv_ranges_del_all(&plocalports->ranges));
248   }
249 
250   netwib_er(netwib_buf_init_mallocdefault(&buf));
251   prompt = ':';
252   while (NETWIB_TRUE) {
253     netwib_er(netwib_priv_kbd_buf_append(pmessage, pdefaultlist,
254                                          NETWIB_TRUE, prompt, NETWIB_FALSE,
255                                          &buf));
256     if (netwib__buf_ref_data_size(&buf) == 0) {
257       if (pdefaultlist != NULL) {
258         netwib_er(netwib_ports_add_buf(pports, pdefaultlist));
259         break;
260       }
261     }
262     ret = netwib_ports_add_buf(plocalports, &buf);
263     if (ret == NETWIB_ERR_OK) {
264       netwib_er(netwib_ports_add_ports(pports, plocalports));
265       break;
266     }
267     netwib_er(netwib_priv_ranges_del_all(&plocalports->ranges));
268     netwib__buf_reinit(&buf);
269     prompt = '>';
270   }
271 
272   netwib_er(netwib_buf_close(&buf));
273   netwib_er(netwib_ports_close(&plocalports));
274 
275   return(NETWIB_ERR_OK);
276 }
277 
278 /*-------------------------------------------------------------*/
netwib_ports_del_port(netwib_ports * pports,netwib_port port)279 netwib_err netwib_ports_del_port(netwib_ports *pports,
280                                  netwib_port port)
281 {
282   netwib_byte portarray[NETWIB_PORT_LEN];
283 
284   /* parameter verification */
285   if (pports == NULL) {
286     return(NETWIB_ERR_PANULLPTR);
287   }
288 #if NETWIB_DEBUG_LEAK==1
289   netwib_er(netwib_debug_leak_valid_ports(pports));
290 #endif
291 
292   /* add item */
293   portarray[0] = netwib_c2_uint16_0(port);
294   portarray[1] = netwib_c2_uint16_1(port);
295   netwib_er(netwib_priv_ranges_del(&pports->ranges, portarray));
296 
297   return(NETWIB_ERR_OK);
298 }
299 
300 /*-------------------------------------------------------------*/
netwib_ports_del_portrange(netwib_ports * pports,netwib_port infport,netwib_port support)301 netwib_err netwib_ports_del_portrange(netwib_ports *pports,
302                                       netwib_port infport,
303                                       netwib_port support)
304 {
305   netwib_byte infportarray[NETWIB_PORT_LEN], supportarray[NETWIB_PORT_LEN];
306 
307   /* parameter verification */
308   if (pports == NULL) {
309     return(NETWIB_ERR_PANULLPTR);
310   }
311 #if NETWIB_DEBUG_LEAK==1
312   netwib_er(netwib_debug_leak_valid_ports(pports));
313 #endif
314 
315   /* add item */
316   infportarray[0] = netwib_c2_uint16_0(infport);
317   infportarray[1] = netwib_c2_uint16_1(infport);
318   supportarray[0] = netwib_c2_uint16_0(support);
319   supportarray[1] = netwib_c2_uint16_1(support);
320   netwib_er(netwib_priv_ranges_del_range(&pports->ranges, infportarray,
321                                          supportarray));
322 
323   return(NETWIB_ERR_OK);
324 }
325 
326 /*-------------------------------------------------------------*/
netwib_ports_del_ports(netwib_ports * pports,netwib_constports * pportstodel)327 netwib_err netwib_ports_del_ports(netwib_ports *pports,
328                                   netwib_constports *pportstodel)
329 {
330   netwib_priv_ranges_index rangesindex;
331   netwib_byte infportarray[NETWIB_PORT_LEN], supportarray[NETWIB_PORT_LEN];
332   netwib_err ret;
333 
334   /* parameter verification */
335   if (pports == NULL) {
336     return(NETWIB_ERR_PANULLPTR);
337   }
338 #if NETWIB_DEBUG_LEAK==1
339   netwib_er(netwib_debug_leak_valid_ports(pports));
340   netwib_er(netwib_debug_leak_valid_ports(pportstodel));
341 #endif
342 
343   netwib_er(netwib_priv_ranges_index_init(&pportstodel->ranges, &rangesindex));
344   ret = NETWIB_ERR_OK;
345   while(NETWIB_TRUE) {
346     ret = netwib_priv_ranges_index_next_range(&rangesindex, infportarray,
347                                               supportarray);
348     if (ret != NETWIB_ERR_OK) {
349       if (ret == NETWIB_ERR_DATAEND) ret = NETWIB_ERR_OK;
350       break;
351     }
352     netwib_er(netwib_priv_ranges_del_range(&pports->ranges, infportarray,
353                                            supportarray));
354   }
355   netwib_er(netwib_priv_ranges_index_close(&rangesindex));
356 
357   return(ret);
358 }
359 
360 /*-------------------------------------------------------------*/
netwib_ports_contains_port(netwib_constports * pports,netwib_port port,netwib_bool * pyes)361 netwib_err netwib_ports_contains_port(netwib_constports *pports,
362                                       netwib_port port,
363                                       netwib_bool *pyes)
364 {
365   netwib_byte portarray[NETWIB_PORT_LEN];
366 
367   /* parameter verification */
368   if (pports == NULL) {
369     return(NETWIB_ERR_PANULLPTR);
370   }
371 #if NETWIB_DEBUG_LEAK==1
372   netwib_er(netwib_debug_leak_valid_ports(pports));
373 #endif
374 
375   /* add item */
376   portarray[0] = netwib_c2_uint16_0(port);
377   portarray[1] = netwib_c2_uint16_1(port);
378   netwib_er(netwib_priv_ranges_contains(&pports->ranges, portarray, pyes));
379 
380   return(NETWIB_ERR_OK);
381 }
382 
383 /*-------------------------------------------------------------*/
netwib_ports_contains_portrange(netwib_constports * pports,netwib_port infport,netwib_port support,netwib_bool * pyes)384 netwib_err netwib_ports_contains_portrange(netwib_constports *pports,
385                                            netwib_port infport,
386                                            netwib_port support,
387                                            netwib_bool *pyes)
388 {
389   netwib_byte infportarray[NETWIB_PORT_LEN], supportarray[NETWIB_PORT_LEN];
390 
391   /* parameter verification */
392   if (pports == NULL) {
393     return(NETWIB_ERR_PANULLPTR);
394   }
395 #if NETWIB_DEBUG_LEAK==1
396   netwib_er(netwib_debug_leak_valid_ports(pports));
397 #endif
398 
399   /* add item */
400   infportarray[0] = netwib_c2_uint16_0(infport);
401   infportarray[1] = netwib_c2_uint16_1(infport);
402   supportarray[0] = netwib_c2_uint16_0(support);
403   supportarray[1] = netwib_c2_uint16_1(support);
404   netwib_er(netwib_priv_ranges_contains_range(&pports->ranges, infportarray,
405                                               supportarray, pyes));
406 
407   return(NETWIB_ERR_OK);
408 }
409 
410 /*-------------------------------------------------------------*/
netwib_buf_append_ports(netwib_constports * pports,netwib_buf * pbuf)411 netwib_err netwib_buf_append_ports(netwib_constports *pports,
412                                    netwib_buf *pbuf)
413 {
414   netwib_priv_ranges_index rangesindex;
415   netwib_byte infportarray[NETWIB_PORT_LEN], supportarray[NETWIB_PORT_LEN];
416   netwib_port infport, support;
417   netwib_bool needcomma;
418   netwib_uint32 savedsize=0;
419   netwib_err ret;
420 
421   /* parameter verification */
422   if (pports == NULL) {
423     return(NETWIB_ERR_PANULLPTR);
424   }
425 #if NETWIB_DEBUG_LEAK==1
426   netwib_er(netwib_debug_leak_valid_ports(pports));
427 #endif
428 
429   /* save position in case of error */
430   if (pbuf != NULL) {
431     savedsize = netwib__buf_ref_data_size(pbuf);
432   }
433 
434   netwib_er(netwib_priv_ranges_index_init(&pports->ranges, &rangesindex));
435   ret = NETWIB_ERR_OK;
436   needcomma = NETWIB_FALSE;
437   while(NETWIB_TRUE) {
438     ret = netwib_priv_ranges_index_next_range(&rangesindex, infportarray,
439                                               supportarray);
440     if (ret != NETWIB_ERR_OK) {
441       if (ret == NETWIB_ERR_DATAEND) ret = NETWIB_ERR_OK;
442       break;
443     }
444     if (needcomma) {
445       ret = netwib_buf_append_byte(',', pbuf);
446       if (ret != NETWIB_ERR_OK) {
447         break;
448       }
449     } else {
450       needcomma = NETWIB_TRUE;
451     }
452     infport = netwib_c2_uint16_2(infportarray[0], infportarray[1]);
453     support = netwib_c2_uint16_2(supportarray[0], supportarray[1]);
454     ret = netwib_buf_append_port(infport, pbuf);
455     if (ret != NETWIB_ERR_OK) {
456       break;
457     }
458     if (infport != support) {
459       ret = netwib_buf_append_byte('-', pbuf);
460       if (ret != NETWIB_ERR_OK) {
461         break;
462       }
463       ret = netwib_buf_append_port(support, pbuf);
464       if (ret != NETWIB_ERR_OK) {
465         break;
466       }
467     }
468   }
469   netwib_er(netwib_priv_ranges_index_close(&rangesindex));
470 
471   /* on space error, restore first pos */
472   if (ret != NETWIB_ERR_OK) {
473     if (pbuf != NULL) {
474       pbuf->endoffset = pbuf->beginoffset + savedsize;
475     }
476   }
477   return(ret);
478 }
479