revert between 56095 -> 55830 in arch
[AROS.git] / workbench / network / stacks / AROSTCP / bsdsocket / kern / amiga_netdb.c
blob691aeb4562571b4b400f3c537e7ae9b73343784b
1 /*
2 * Copyright (C) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>
3 * Helsinki University of Technology, Finland.
4 * All rights reserved.
5 * Copyright (C) 2005 - 2019 The AROS Dev Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
19 * MA 02111-1307, USA.
23 #include <conf.h>
25 #include <proto/dos.h>
26 #include <proto/bsdsocket.h>
28 #include <dos/dos.h>
29 #include <dos/rdargs.h>
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/syslog.h>
34 #include <sys/socket.h>
35 #include <sys/malloc.h>
36 #include <sys/mbuf.h>
38 #include <api/amiga_api.h>
39 #include <kern/amiga_gui.h>
40 #include <kern/amiga_includes.h>
41 #include <kern/amiga_config.h>
42 #include <kern/amiga_netdb.h>
43 #include <kern/accesscontrol.h>
45 #include "net/netdbpaths.h"
46 #include <net/sana2config.h>
47 #include <net/route.h>
48 #include <netinet/in.h>
49 #include <protos/net/if_protos.h>
51 extern struct ifnet *iface_make(struct ssconfig *ifc);
53 LONG read_netdb(struct NetDataBase *ndb, UBYTE *fname,
54 UBYTE** errstrp, struct CSource *res,
55 int prefixindex, ULONG flags);
58 * Global pointer for the NetDataBase
60 struct NetDataBase *NDB = NULL;
63 * Global lock for the NetDatabase
65 struct SignalSemaphore ndb_Lock;
68 * Dynamic items Database (for entries supplied by DHCP)
70 struct DynDataBase DynDB;
73 * NDB Update Counter (used to keep resolver cache up to date)
75 ULONG ndb_Serial;
78 * Default netdatabase name
80 STRPTR netdbname = netdb_path;
82 /*
83 * Templates for Arexx commands and DB files
85 STRPTR NETDBENTRY =
86 "WITH,I=INTERFACE,H=HOST,N=NET,S=SERVICE,P=PROTOCOL,R=ROUTE,NS=NAMESERVER,DO=DOMAIN,RC,ACC=ACCESS";
88 enum ndbtype { KNDB_WITH, KNDB_IFACE, KNDB_HOST, KNDB_NET, KNDB_SERV, KNDB_PROTO,
89 KNDB_RT, KNDB_DNS, KNDB_DOM, KNDB_RC, KNDB_ACC };
91 STRPTR NETDBTEMPLATE =
92 "$NAME$/A,$ENTRY$/A,$ALIAS$/M";
94 STRPTR PROTOCOL_TEMPLATE =
95 "$NAME$/A,$NUMBER$/A/N,$ALIAS$/M";
97 enum ndbarg { KNDB_NAME, KNDB_DATA, KNDB_ALIAS };
99 #define NDBARGS 3
101 STRPTR ROUTE_TEMPLATE =
102 "HOST/S,NET/S,DEST/A,GW=GATEWAY/A";
104 enum rtarg { KRT_HOST, KRT_NET, KRT_DEST, KRT_GATE, RTARGS };
106 STRPTR ACCESS_TEMPLATE =
107 "$PORT$/A,$HOSTMASK$/A,$ACCESS$/A,LOG/S";
109 enum accarg { KACC_PORT, KACC_HOSTMASK, KACC_ACCESS, KACC_LOG };
111 #define ACCARGS 4
113 STRPTR WITH_TEMPLATE =
114 "$FILE$/A,PREFIX/K";
115 #define WITHARGS 2
116 enum witharg { WITH_FILE, WITH_PREFIX };
118 /* prototypes for the netdb parsing functions */
120 LONG addwith(struct NetDataBase *ndb,
121 struct RDArgs *rdargs, UBYTE **errstrp, struct CSource *res, ULONG flags);
122 LONG addifent(struct NetDataBase *ndb,
123 struct RDArgs *rdargs, UBYTE **errstrp, struct CSource *res, ULONG flags);
124 LONG addhostent(struct NetDataBase *ndb,
125 struct RDArgs *rdargs, UBYTE **errstrp, struct CSource *res, ULONG flags);
126 LONG addnetent(struct NetDataBase *ndb,
127 struct RDArgs *rdargs, UBYTE **errstrp, struct CSource *res, ULONG flags);
128 LONG addservent(struct NetDataBase *ndb,
129 struct RDArgs *rdargs, UBYTE **errstrp, struct CSource *res, ULONG flags);
130 LONG addprotoent(struct NetDataBase *ndb,
131 struct RDArgs *rdargs, UBYTE **errstrp, struct CSource *res, ULONG flags);
132 LONG addrtent(struct NetDataBase *ndb,
133 struct RDArgs *rdargs, UBYTE **errstrp, struct CSource *res, ULONG flags);
134 LONG addnameservent(struct NetDataBase *ndb,
135 struct RDArgs *rdargs, UBYTE **errstrp, struct CSource *res, ULONG flags);
136 LONG adddomainent(struct NetDataBase *ndb,
137 struct RDArgs *rdargs, UBYTE **errstrp, struct CSource *res, ULONG flags);
138 LONG addrcent(struct NetDataBase *ndb,
139 struct RDArgs *rdargs, UBYTE **errstrp, struct CSource *res, ULONG flags);
140 LONG addaccessent(struct NetDataBase *ndb,
141 struct RDArgs *rdargs, UBYTE **errstrp, struct CSource *res, ULONG flags);
142 LONG addndbent(struct NetDataBase *ndb,
143 struct RDArgs *rdargs, UBYTE **errstrp, struct CSource *res, ULONG ifflags);
145 typedef LONG (*ndb_parse_f)(struct NetDataBase *ndb,
146 struct RDArgs *rdargs, UBYTE **errstrp, struct CSource *res, ULONG flags);
148 /* Array of parsing functions. Note that the order is same as in the
149 * NETDBENTRY.
151 ndb_parse_f ndb_parse_funs[] = {
152 addwith,
153 addifent,
154 addhostent,
155 addnetent,
156 addservent,
157 addprotoent,
158 addrtent,
159 addnameservent,
160 adddomainent,
161 addrcent,
162 addaccessent
166 * Alloc a NetDataBase
168 struct NetDataBase *
169 alloc_netdb(struct NetDataBase *ndb)
171 #if defined(__AROS__)
172 D(bug("[AROSTCP](amiga_netdb.c) alloc_netdb()\n"));
173 #endif
175 if (ndb ||
176 (ndb = bsd_malloc(sizeof (*NDB), M_NETDB, M_WAITOK))) {
177 struct MinList *gl;
179 for (gl = (struct MinList *)&ndb->ndb_Hosts;
180 gl <= (struct MinList *)&ndb->ndb_Domains;
181 gl++)
182 NewList((struct List *)gl);
186 ndb->ndb_AccessCount = 0;
187 if ((ndb->ndb_AccessTable =
188 bsd_malloc(TMPACTSIZE, M_NETDB, M_WAITOK)) == NULL) {
189 bsd_free(ndb, M_NETDB);
190 ndb = NULL;
192 #if defined(__AROS__)
193 D(bug("[AROSTCP](amiga_netdb.c) alloc_netdb: Allocated ndb = 0x%p, ndb_AccessTable = 0x%p\n", ndb, ndb->ndb_AccessTable));
194 #endif
195 DNETDB(else __log(LOG_DEBUG,"Allocated ndb = 0x%p, ndb_AccessTable = 0x%p", ndb, ndb->ndb_AccessTable);)
196 return ndb;
200 * Free a NetDataBase
201 * Caller must have a write lock on NDB
203 void
204 free_netdb(struct NetDataBase *ndb)
206 struct GenentNode *gn;
207 struct MinList *gl;
208 #if defined(__AROS__)
209 D(bug("[AROSTCP](amiga_netdb.c) free_netdb( 0x%p )\n", ndb));
210 #endif
211 for (gl = (struct MinList *)&ndb->ndb_Hosts;
212 gl <= (struct MinList *)&ndb->ndb_Domains;
213 gl++)
214 while (gn = (struct GenentNode *)RemHead((struct List *)gl))
215 bsd_free(gn, M_NETDB);
217 if (ndb->ndb_AccessTable != NULL) {
218 bsd_free(ndb->ndb_AccessTable, M_NETDB);
219 ndb->ndb_AccessTable = NULL;
221 bsd_free(ndb, M_NETDB);
224 #ifdef DEBUG
225 static UBYTE * zap;
226 static size_t zap_size;
227 #endif
230 * Copy alias list to ato, alias strings and name to cto
232 static void
233 aliascpy(UBYTE *cto, UBYTE *name, UBYTE**ato, UBYTE **afrom)
235 #ifdef DEBUG
236 UBYTE *logname = name;
237 #endif
238 #if defined(__AROS__)
239 D(bug("[AROSTCP](amiga_netdb.c) aliascopy()\n"));
240 #endif
242 do {
243 while(*cto++ = *name++);
244 } while (afrom && (name = *afrom++) && (*ato++ = cto));
246 *ato = NULL;
248 #ifdef DEBUG
249 if (cto != zap + zap_size) {
250 __log(LOG_ERR, "%s: mismatch in size %ld != expected %ld\n",
251 logname, cto - (UBYTE *)zap, zap_size);
253 #endif
257 * Allocate a netdb node
259 * nodesize is the size of the base structure, additional space
260 * is allocated for the name and the aliases.
261 * alias is NULL terminated array of alias name pointers.
262 * Number of aliases is returned via aliasp.
264 * size field of the allocated node is set to the total size - size for
265 * the MinNode and the size field itself.
267 static void *
268 node_alloc(size_t nodesize, UBYTE *name, UBYTE **alias, int *aliasp)
270 struct GenentNode *gn;
271 #if defined(__AROS__)
272 D(bug("[AROSTCP](amiga_netdb.c) node_alloc()\n"));
273 #endif
275 nodesize += strlen(name) + 1; /* Add space needed for the name */
277 *aliasp = 1;
278 nodesize += sizeof (char*); /* Alias list NULL terminator */
280 /* Calculate the size of the aliases */
281 if (alias) {
282 while (*alias) {
283 (*aliasp)++;
284 nodesize += strlen(*alias++) + 1 + sizeof (char*);
287 gn = bsd_malloc(nodesize, M_NETDB, M_WAITOK);
289 * set the ent size
291 if (gn)
292 gn->gn_EntSize = nodesize - sizeof (struct GenentNode);
294 #ifdef DEBUG
295 zap_size = nodesize;
296 zap = (char *)gn;
297 #endif
298 return gn;
302 * Parse an include entry.
304 LONG
305 addwith(struct NetDataBase *ndb,
306 struct RDArgs *rdargs,
307 UBYTE **errstrp, struct CSource *res, ULONG flags)
309 // UBYTE result[REPLYBUFLEN + 1];
310 //struct CSource res;
311 LONG retval = RETURN_OK;
312 IPTR Args[WITHARGS] = { 0 };
313 int which;
315 #if defined(__AROS__)
316 D(bug("[AROSTCP](amiga_netdb.c) addwith()\n"));
317 #endif
319 /* res.CS_Buffer = result;
320 res.CS_Length = sizeof (result);
321 res.CS_CurChr = 0;*/
323 if (rdargs = ReadArgs(WITH_TEMPLATE, Args, rdargs)) {
324 if (Args[WITH_PREFIX] == 0) /* no prefix given */
325 which = -1;
326 else {
327 /* match given prefix */
328 which = FindArg(NETDBENTRY, (UBYTE *)Args[WITH_PREFIX]);
329 if (which < 0) {
330 *errstrp = ERR_VALUE;
331 retval = RETURN_WARN;
334 if (retval == RETURN_OK) {
335 retval = read_netdb(ndb, (UBYTE *)Args[WITH_FILE], errstrp, res,
336 which, flags);
338 FreeArgs(rdargs);
339 } else {
340 *errstrp = ERR_SYNTAX; retval = RETURN_WARN;
342 return retval;
345 /* Copy an address */
346 static int inline setaddr(struct sockaddr_in *sa, char *addr, u_short af)
348 sa->sin_len = sizeof(struct sockaddr_in);
349 sa->sin_family = af;
350 return __inet_aton(addr, &sa->sin_addr);
354 * Parse an interface entry.
356 LONG
357 addifent(struct NetDataBase *ndb,
358 struct RDArgs *rdargs,
359 UBYTE **errstrp, struct CSource *res, ULONG flags)
361 struct ssconfig *ssc;
362 struct ifnet *ifp;
363 struct ifaliasreq ifr;
364 char *cp, *ep;
365 LONG retval = RETURN_OK;
367 #if defined(__AROS__)
368 D(bug("[AROSTCP](amiga_netdb.c) addifent()\n"));
369 #endif
371 if (flags & (NETDB_IFF_MODIFYOLD|NETDB_IFF_ADDNEW)) {
372 ssc = ssconfig_parse(rdargs);
373 if (ssc) {
374 ifp = ifunit(ssc->args->a_name);
375 if ((!ifp) && (flags & NETDB_IFF_ADDNEW)) {
376 DIFCONF(Printf("Adding new interface %s\n", ssc->args->a_name);)
377 cp = strncpy(ssc->name, ssc->args->a_name, IFNAMSIZ);
378 ssc->name[IFNAMSIZ-1] = '\0';
380 for (; *cp; cp++)
381 if (*cp >= '0' && *cp <= '9')
382 break;
384 ep = cp;
385 for (ssc->unit = 0; *cp >= '0' && *cp <= '9'; )
386 ssc->unit = ssc->unit * 10 + *cp++ - '0';
388 *ep = 0;
389 ifp = iface_make(ssc);
390 if (!ifp) {
391 #if defined(__AROS__)
392 D(bug("[AROSTCP](amiga_netdb.c) addifent: failed to create interface '%s'\n", ssc->args->a_name));
393 #endif
394 *errstrp = ERR_MEMORY;
395 retval = RETURN_FAIL;
397 else
399 #if defined(__AROS__)
400 D(bug("[AROSTCP](amiga_netdb.c) addifent: created new interface '%s'\n", ssc->args->a_name));
401 #endif
402 flags |= NETDB_IFF_MODIFYOLD;
405 if ((ifp) && (flags & NETDB_IFF_MODIFYOLD))
407 #if defined(__AROS__)
408 D(bug("[AROSTCP](amiga_netdb.c) addifent: configuring interface '%s'\n", ssc->args->a_name));
409 #endif
410 DIFCONF(Printf("Setting up interface %s\n", ssc->args->a_name);)
411 memset (&ifr, 0, sizeof (ifr));
412 if (ssc->args->a_ip) {
413 if (!ssc->args->a_up) {
414 DIFCONF(Printf("> No auto-online\n");)
415 ifp->if_flags |= IFF_NOUP;
417 DIFCONF(Printf("> IP address: %s\n", ssc->args->a_ip);)
418 if (stricmp(ssc->args->a_ip, "DHCP")) {
419 ifp->if_data.ifi_aros_usedhcp = 0;
420 if (setaddr ((struct sockaddr_in *)&ifr.ifra_addr, ssc->args->a_ip, AF_INET)) {
421 if (ssc->args->a_netmask) {
422 DIFCONF(Printf("> Netmask: %s\n", ssc->args->a_netmask);)
423 if (!setaddr ((struct sockaddr_in *)&ifr.ifra_mask, ssc->args->a_netmask, AF_UNSPEC)) {
424 *errstrp = ERR_SYNTAX;
425 retval = RETURN_WARN;
428 in_control(NULL, SIOCAIFADDR, &ifr, ifp);
429 } else {
430 *errstrp = ERR_SYNTAX;
431 retval = RETURN_WARN;
433 } else {
434 DIFCONF(Printf("> Using DHCP\n");)
435 ifp->if_data.ifi_aros_usedhcp = 1;
436 if (ssc->args->a_up) {
437 if (api_state == API_SHOWN)
438 run_dhclient(ifp);
439 else
440 ifp->if_flags |= IFF_DELAYUP;
445 else
447 #if defined(__AROS__)
448 D(bug("[AROSTCP](amiga_netdb.c) addifent: Interface named '%s' already exists..\n", ssc->args->a_name));
449 #endif
451 ssconfig_free(ssc);
452 } else {
453 *errstrp = ERR_SYNTAX;
454 retval = RETURN_WARN;
457 return retval;
462 * Parse a service entry.
464 LONG
465 addservent(struct NetDataBase *ndb,
466 struct RDArgs *rdargs,
467 UBYTE **errstrp, struct CSource *res, ULONG flags)
469 LONG retval;
470 IPTR Args[NDBARGS] = { 0 };
471 struct ServentNode *sn;
472 int aliases, plen;
474 #if defined(__AROS__)
475 D(bug("[AROSTCP](amiga_netdb.c) addservent()\n"));
476 #endif
478 if (rdargs = ReadArgs(NETDBTEMPLATE, Args, rdargs)) {
479 /* convert port number */
480 UBYTE *s_proto = (UBYTE*)Args[KNDB_DATA];
481 LONG tmp;
482 if ((plen = StrToLong(s_proto, &tmp)) > 0 &&
483 s_proto[plen++] == '/') {
484 Args[KNDB_DATA] = tmp;
485 int protonamelen = strlen(s_proto = s_proto + plen) + 1;
486 sn = node_alloc(sizeof (*sn) + protonamelen,
487 (UBYTE*)Args[KNDB_NAME],
488 (UBYTE **)Args[KNDB_ALIAS], &aliases);
489 if (sn) {
490 UBYTE **alias = (UBYTE **)(sn+1);
491 UBYTE *name = (UBYTE *)(alias + aliases);
493 sn->sn_Ent.s_port = Args[KNDB_DATA];
494 sn->sn_Ent.s_proto = strcpy(name, s_proto);
495 sn->sn_Ent.s_name = name + protonamelen;
496 sn->sn_Ent.s_aliases = (char **)alias;
498 /* Copy aliases */
499 aliascpy(sn->sn_Ent.s_name, (UBYTE*)Args[KNDB_NAME],
500 alias, (UBYTE **)Args[KNDB_ALIAS]);
501 AddTail((struct List*)&ndb->ndb_Services, (struct Node*)sn);
502 retval = RETURN_OK;
503 } else {
504 *errstrp = ERR_MEMORY; retval = RETURN_FAIL;
506 } else {
507 *errstrp = ERR_VALUE; retval = RETURN_WARN;
509 FreeArgs(rdargs);
510 } else {
511 *errstrp = ERR_SYNTAX; retval = RETURN_WARN;
513 return retval;
517 * Parse a host entry.
519 * NOTE: The host entry has the address in the 'name' and the official name
520 * in the 'data'.
522 LONG
523 addhostent(struct NetDataBase *ndb,
524 struct RDArgs *rdargs,
525 UBYTE **errstrp, struct CSource *res, ULONG flags)
527 LONG retval;
528 IPTR Args[NDBARGS] = { 0 };
529 struct HostentNode *hn;
530 struct in_addr addr;
531 int aliases;
533 #if defined(__AROS__)
534 D(bug("[AROSTCP](amiga_netdb.c) addhostent()\n"));
535 #endif
537 if (rdargs = ReadArgs(NETDBTEMPLATE, Args, rdargs)) {
538 /* convert ip address */
539 if (__inet_aton((char*)Args[KNDB_NAME], &addr)) {
540 hn = node_alloc(sizeof (*hn) + 2*sizeof (&addr) + sizeof (addr),
541 (UBYTE*)Args[KNDB_DATA],
542 (UBYTE **)Args[KNDB_ALIAS], &aliases);
543 if (hn) {
544 struct in_addr **addrtbl = (struct in_addr **)(hn + 1);
545 UBYTE **alias = (UBYTE **)((UBYTE*)(addrtbl + 2) + sizeof (addr));
546 UBYTE *name = (UBYTE *)(alias + aliases);
548 hn->hn_Ent.h_addrtype = AF_INET;
549 hn->hn_Ent.h_length = sizeof (addr);
550 hn->hn_Ent.h_addr_list = (char **)addrtbl;
551 hn->hn_Ent.h_name = name;
552 hn->hn_Ent.h_aliases = (char **)alias;
554 /* Make address list */
555 addrtbl[0] = (struct in_addr *)(addrtbl + 2);
556 addrtbl[1] = NULL;
557 bcopy(&addr, addrtbl[0], sizeof (addr));
559 /* Copy aliases */
560 aliascpy(hn->hn_Ent.h_name, (UBYTE*)Args[KNDB_DATA],
561 alias, (UBYTE **)Args[KNDB_ALIAS]);
562 AddTail((struct List*)&ndb->ndb_Hosts, (struct Node*)hn);
563 retval = RETURN_OK;
564 } else {
565 *errstrp = ERR_MEMORY; retval = RETURN_FAIL;
567 } else {
568 *errstrp = ERR_VALUE; retval = RETURN_WARN;
570 FreeArgs(rdargs);
571 } else {
572 *errstrp = ERR_SYNTAX; retval = RETURN_WARN;
574 return retval;
578 * Parse a net entry.
580 LONG
581 addnetent(struct NetDataBase *ndb,
582 struct RDArgs *rdargs,
583 UBYTE **errstrp, struct CSource *res, ULONG flags)
585 LONG retval;
586 IPTR Args[NDBARGS] = { 0 };
587 struct NetentNode *nn;
588 struct in_addr addr;
589 int aliases;
591 #if defined(__AROS__)
592 D(bug("[AROSTCP](amiga_netdb.c) addnetent()\n"));
593 #endif
595 if (rdargs = ReadArgs(NETDBTEMPLATE, Args, rdargs)) {
596 /* convert ip address */
597 if (__inet_aton((char*)Args[KNDB_DATA], &addr)) {
598 nn = node_alloc(sizeof (*nn),
599 (UBYTE*)Args[KNDB_NAME],
600 (UBYTE **)Args[KNDB_ALIAS], &aliases);
601 if (nn) {
602 UBYTE **alias = (UBYTE **)(nn + 1);
603 UBYTE *name = (UBYTE *)(alias + aliases);
605 nn->nn_Ent.n_addrtype = AF_INET;
606 nn->nn_Ent.n_name = name;
607 nn->nn_Ent.n_aliases = (char **)alias;
608 bcopy(&addr, &nn->nn_Ent.n_net, sizeof (addr));
610 /* Copy aliases */
611 aliascpy(nn->nn_Ent.n_name, (UBYTE*)Args[KNDB_NAME],
612 alias, (UBYTE **)Args[KNDB_ALIAS]);
613 AddTail((struct List*)&ndb->ndb_Networks, (struct Node*)nn);
614 retval = RETURN_OK;
615 } else {
616 *errstrp = ERR_MEMORY; retval = RETURN_FAIL;
618 } else {
619 *errstrp = ERR_VALUE; retval = RETURN_WARN;
621 FreeArgs(rdargs);
622 } else {
623 *errstrp = ERR_SYNTAX; retval = RETURN_WARN;
625 return retval;
629 * Parse a protocol entry.
631 LONG
632 addprotoent(struct NetDataBase *ndb,
633 struct RDArgs *rdargs,
634 UBYTE **errstrp, struct CSource *res, ULONG flags)
636 LONG retval;
637 IPTR Args[NDBARGS] = { 0 };
638 struct ProtoentNode *pn;
639 int aliases;
641 #if defined(__AROS__)
642 D(bug("[AROSTCP](amiga_netdb.c) addprotoent()\n"));
643 #endif
645 if (rdargs = ReadArgs(PROTOCOL_TEMPLATE, Args, rdargs)) {
647 if (Args[KNDB_DATA]) {
648 pn = node_alloc(sizeof (*pn), (UBYTE*)Args[KNDB_NAME],
649 (UBYTE **)Args[KNDB_ALIAS], &aliases);
650 if (pn) {
651 UBYTE **alias = (UBYTE **)(pn+1);
652 UBYTE *name = (UBYTE *)(alias + aliases);
654 pn->pn_Ent.p_name = name;
655 pn->pn_Ent.p_aliases = (char **)alias;
656 pn->pn_Ent.p_proto = *(LONG *)Args[KNDB_DATA];
658 /* Copy name and aliases */
659 aliascpy(name, (UBYTE*)Args[KNDB_NAME],
660 alias, (UBYTE **)Args[KNDB_ALIAS]);
661 AddTail((struct List*)&ndb->ndb_Protocols, (struct Node*)pn);
662 retval = RETURN_OK;
663 } else {
664 *errstrp = ERR_MEMORY; retval = RETURN_FAIL;
666 } else {
667 *errstrp = ERR_VALUE; retval = RETURN_WARN;
669 FreeArgs(rdargs);
670 } else {
671 *errstrp = ERR_SYNTAX; retval = RETURN_WARN;
673 return retval;
677 * Parse a route entry
679 LONG
680 addrtent(struct NetDataBase *ndb,
681 struct RDArgs *rdargs,
682 UBYTE **errstrp, struct CSource *res, ULONG flags)
684 LONG retval;
685 IPTR Args[RTARGS] = { 0 };
686 struct ortentry route;
688 #if defined(__AROS__)
689 D(bug("[AROSTCP](amiga_netdb.c) addrtent()\n"));
690 #endif
692 if (rdargs = ReadArgs(ROUTE_TEMPLATE, Args, rdargs)) {
693 if (!(strcmp(strupr((APTR)Args[KRT_DEST]), "DEFAULT"))){
694 struct sockaddr_in *rodst_saddr = (struct sockaddr_in *)&route.rt_dst;
695 rodst_saddr->sin_addr.s_addr = 0;
696 route.rt_dst.sa_family = AF_INET;
697 route.rt_dst.sa_len = sizeof(struct sockaddr_in);
698 } else {
699 if (!(setaddr((struct sockaddr_in *)&route.rt_dst, (APTR)Args[KRT_DEST], AF_INET)))
700 goto bad;
703 if (setaddr((struct sockaddr_in *)&route.rt_gateway, (APTR)Args[KRT_GATE], AF_INET)) {
704 route.rt_flags = RTF_UP | RTF_GATEWAY;
705 if (Args[KRT_HOST])
706 route.rt_flags |= RTF_HOST;
707 rtioctl(SIOCADDRT, (caddr_t)&route);
708 retval = RETURN_OK;
709 } else {
710 bad:
711 *errstrp = ERR_SYNTAX;
712 retval = RETURN_WARN;
714 FreeArgs(rdargs);
716 return retval;
720 * Parse a Name Server entry
722 LONG
723 addnameservent(struct NetDataBase *ndb,
724 struct RDArgs *rdargs,
725 UBYTE **errstrp, struct CSource *res, ULONG flags)
727 UBYTE Buffer[KEYWORDLEN];
728 LONG BufLen = sizeof (Buffer);
729 struct in_addr ns_addr;
730 struct NameserventNode *nsn;
732 #if defined(__AROS__)
733 D(bug("[AROSTCP](amiga_netdb.c) addnameservent()\n"));
734 #endif
736 /* TODO: NicJA - Where does CHECK_POINTER() Come from? */
737 #if !defined(__AROS__)
738 CHECK_POINTER(ndb);
739 #endif
741 if (ReadItem(Buffer, BufLen, &rdargs->RDA_Source) <= 0) {
742 #if defined(__AROS__)
743 D(bug("[AROSTCP](amiga_netdb.c) addnameservent: Error in syntax\n"));
744 #endif
745 *errstrp = ERR_SYNTAX;
746 return RETURN_WARN;
748 if (!__inet_aton(Buffer, &ns_addr)) {
749 #if defined(__AROS__)
750 D(bug("[AROSTCP](amiga_netdb.c) addnameservent: error with address\n"));
751 #endif
752 *errstrp = ERR_VALUE;
753 return RETURN_WARN;
755 if ((nsn = bsd_malloc(sizeof (*nsn), M_NETDB, M_WAITOK)) == NULL) {
756 #if defined(__AROS__)
757 D(bug("[AROSTCP](amiga_netdb.c) addnameservent: couldnt allocate entry\n"));
758 #endif
759 *errstrp = ERR_MEMORY;
760 return RETURN_FAIL;
762 nsn->nsn_EntSize = sizeof (nsn->nsn_Ent);
763 nsn->nsn_Ent.ns_addr.s_addr = ns_addr.s_addr;
765 /* TODO: NicJA - Where does CHECK_POINTER() Come from? */
766 #if !defined(__AROS__)
767 CHECK_POINTER(nsn);
768 #endif
770 #if defined(__AROS__)
771 D(bug("[AROSTCP](amiga_netdb.c) addnameservent: Added nameserver %s (0x%08lx) to netdb = 0x%08lx\n",Buffer, nsn->nsn_Ent.ns_addr.s_addr, ndb));
772 #endif
773 DNETDB(__log(LOG_DEBUG,"Added nameserver %s (0x%08lx) to netdb = 0x%08lx\n",Buffer, nsn->nsn_Ent.ns_addr.s_addr, ndb);)
775 AddTail((struct List*)&ndb->ndb_NameServers, (struct Node*)nsn);
776 return RETURN_OK;
780 * Parse a Domain Name entry
782 LONG
783 adddomainent(struct NetDataBase *ndb,
784 struct RDArgs *rdargs,
785 UBYTE **errstrp, struct CSource *res, ULONG flags)
787 UBYTE Buffer[REPLYBUFLEN];
788 LONG BufLen = sizeof (Buffer);
789 struct DomainentNode *dn;
790 short nodesize;
792 #if defined(__AROS__)
793 D(bug("[AROSTCP](amiga_netdb.c) adddomainent()\n"));
794 #endif
796 if (ReadItem(Buffer, BufLen, &rdargs->RDA_Source) <= 0) {
797 *errstrp = ERR_SYNTAX;
798 return RETURN_WARN;
800 nodesize = sizeof (*dn) + strlen(Buffer) + 1;
801 if ((dn = bsd_malloc(nodesize, M_NETDB, M_WAITOK)) == NULL) {
802 *errstrp = ERR_MEMORY;
803 return RETURN_FAIL;
805 dn->dn_EntSize = nodesize - sizeof (struct GenentNode);
806 dn->dn_Ent.d_name = (char *)(dn + 1);
808 strcpy((char *)(dn + 1), Buffer);
810 AddTail((struct List*)&ndb->ndb_Domains, (struct Node*)dn);
811 return RETURN_OK;
815 * Parse an RC script entry
817 LONG
818 addrcent(struct NetDataBase *ndb,
819 struct RDArgs *rdargs,
820 UBYTE **errstrp, struct CSource *res, ULONG flags)
822 UBYTE Buffer[REPLYBUFLEN];
823 LONG BufLen = sizeof (Buffer);
824 struct RcentNode *dn;
825 short nodesize;
827 #if defined(__AROS__)
828 D(bug("[AROSTCP](amiga_netdb.c) addrcent()\n"));
829 #endif
831 if (ReadItem(Buffer, BufLen, &rdargs->RDA_Source) <= 0) {
832 *errstrp = ERR_SYNTAX;
833 return RETURN_WARN;
835 nodesize = sizeof (*dn) + strlen(Buffer) + 1;
836 if ((dn = bsd_malloc(nodesize, M_NETDB, M_WAITOK)) == NULL) {
837 *errstrp = ERR_MEMORY;
838 return RETURN_FAIL;
840 dn->rn_EntSize = nodesize - sizeof (struct GenentNode);
841 dn->rn_Ent = (char *)(dn + 1);
843 strcpy((char *)(dn + 1), Buffer);
845 AddTail((struct List*)&ndb->ndb_Rc, (struct Node*)dn);
846 return RETURN_OK;
851 * Parse a access control entry.. after reading the whole netdatabase
852 * access list must be reorganized;
854 LONG
855 addaccessent(struct NetDataBase *ndb,
856 struct RDArgs *rdargs,
857 UBYTE **errstrp, struct CSource *res, ULONG ifflags)
859 LONG retval = RETURN_WARN;
860 IPTR Args[ACCARGS] = { 0 };
862 ULONG host, mask;
863 UWORD port, flags = ACF_CONTINUE;
865 #if defined(__AROS__)
866 D(bug("[AROSTCP](amiga_netdb.c) addaccessent()\n"));
867 #endif
869 if (ndb->ndb_AccessCount >= TMPACTSIZE / sizeof (struct AccessItem)) {
870 *errstrp = "Too many access control items\n";
871 return retval; /* copy propagation expected */
874 if ((rdargs = ReadArgs(ACCESS_TEMPLATE, Args, rdargs)) != NULL) {
876 if (strcmp((char *)Args[KACC_PORT], "*") == 0)
877 port = 0;
878 else if (strcmp((char *)Args[KACC_PORT], "@") == 0) {
879 port = 0; flags |= ACF_PRIVONLY;
881 else if (StrToLong((char *)Args[KACC_PORT], (LONG *)&host) > 0
882 && host != 0) {
883 if (host > 0xffff) {
884 *errstrp = "Illegal port value\n";
885 goto exit;
887 port = host;
889 else {
890 struct ServentNode * entNode;
892 if ((entNode =
893 findServentNode(ndb, (char *)Args[KACC_PORT], "tcp")) != NULL)
894 port = entNode->sn_Ent.s_port;
895 else {
896 *errstrp = "Illegal port value\n";
897 goto exit;
901 int zmask = 0xFFFFFFFF;
902 int i = 0, ls = 0, dots = 0;
904 #define hm ((char *)Args[KACC_HOSTMASK])
906 while ((hm[i] >= '0' && hm[i] <= '9') || hm[i] == '.' || hm[i] == '*') {
907 if (hm[i] == '.') {
908 ls = 0;
909 dots++;
911 else if (hm[i] == '*') {
912 hm[i] = '0';
913 ls = 1;
914 zmask ^= (0xFF000000 >> 8 * dots);
916 i++;
918 if (ls == 1)
919 while (dots++ < 3)
920 zmask ^= (0xFF000000 >> 8 * dots);
922 if (hm[i] == '/') {
923 hm[i++] = '\0';
924 if (__inet_aton(&hm[i], (struct in_addr *)&mask) == 0) {
925 *errstrp = "Illegal mask value\n";
926 goto exit;
929 else
930 mask = 0xffffffff;
932 mask &= zmask;
934 if (__inet_aton(hm, (struct in_addr *)&host) == 0) {
935 *errstrp = "Illegal host value\n";
936 goto exit;
938 #undef hm
940 if (strcmp((char *)Args[KACC_ACCESS], "allow") == 0)
941 flags |= ACF_ALLOW;
942 else if (strcmp((char *)Args[KACC_ACCESS], "deny") != 0) {
943 *errstrp = "Illegal access value\n";
944 goto exit;
947 if (Args[KACC_LOG])
948 flags |= ACF_LOG;
950 ndb->ndb_AccessTable[ndb->ndb_AccessCount].ai_port = port;
951 ndb->ndb_AccessTable[ndb->ndb_AccessCount].ai_host = host;
952 ndb->ndb_AccessTable[ndb->ndb_AccessCount].ai_mask = mask;
953 ndb->ndb_AccessTable[ndb->ndb_AccessCount].ai_flags = flags;
954 ndb->ndb_AccessCount++;
956 retval = 0;
957 exit:
958 FreeArgs(rdargs);
960 else
961 *errstrp = ERR_SYNTAX;
963 return retval;
967 * Add an entry into NetDB.
968 * Caller must have a write lock on ndb
970 LONG
971 addndbent(struct NetDataBase *ndb,
972 struct RDArgs *rdargs,
973 UBYTE **errstrp, struct CSource *res, ULONG flags)
975 if (NDB) {
976 LONG item;
977 enum ndbtype which;
978 UBYTE Buffer[KEYWORDLEN];
980 #if defined(__AROS__)
981 D(bug("[AROSTCP](amiga_netdb.c) addndbent()\n"));
982 #endif
984 /* Get entry type */
985 item = ReadItem(Buffer, sizeof (Buffer), &rdargs->RDA_Source);
987 if (item == 0)
988 return RETURN_OK; /* empty line */
989 if (item < 0) {
990 DNETDB(Printf("addndbent: syntax error\n");)
991 *errstrp = ERR_SYNTAX;
992 return RETURN_WARN;
994 if ((which = FindArg(NETDBENTRY, Buffer)) < 0) {
995 DNETDB(Printf("Unknown keyword\n");)
996 *errstrp = ERR_UNKNOWN;
997 return RETURN_WARN;
1000 DNETDB(Printf("Keyword number: %ld\n", which);)
1001 which = ndb_parse_funs[which](ndb, rdargs, errstrp, res, flags);
1002 return which;
1004 } else {
1005 *errstrp = ERR_NONETDB;
1006 return RETURN_FAIL;
1011 * Read in a NetDataBase file
1013 LONG
1014 read_netdb(struct NetDataBase *ndb, UBYTE *fname,
1015 UBYTE** errstrp, struct CSource *res, int prefixindex, ULONG flags)
1017 LONG warnval = RETURN_OK;
1018 LONG retval = RETURN_OK, ioerr = 0;
1019 UBYTE *p, *buf = AllocMem(CONFIGLINELEN, MEMF_PUBLIC);
1020 struct RDArgs *rdargs;
1021 BPTR fh;
1022 short line = 0;
1023 ndb_parse_f parser;
1024 BPTR lock, oldcd;
1026 #if defined(__AROS__)
1027 D(bug("[AROSTCP](amiga_netdb.c) read_netdb('%s')\n", fname));
1028 #endif
1030 DNETDB(Printf("Reading netdb file: %s\n", fname);)
1031 /* Get an exclusive lock on the database.
1032 * Multiple locks are OK (when this function is called recursively)
1034 LOCK_W_NDB(ndb);
1035 if (ndb_Lock.ss_NestCount > 10) {
1036 UNLOCK_NDB(ndb);
1037 *errstrp = "Too many files included";
1038 #if defined(__AROS__)
1039 D(bug("[AROSTCP](amiga_netdb.c) read_netdb: Too many files included\n"));
1040 #endif
1041 return RETURN_ERROR;
1043 if (buf) {
1045 /* CD to netdb directory */
1046 lock = Lock(db_path, ACCESS_READ);
1047 if (lock)
1048 oldcd = CurrentDir(lock);
1050 if (fh = Open(fname, MODE_OLDFILE)) {
1051 if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) {
1052 /* initialize CSource of the rdargs */
1053 rdargs->RDA_Source.CS_Buffer = buf;
1054 /* initialize rest fields (see dos/rdargs.h) */
1055 rdargs->RDA_DAList = 0;
1056 rdargs->RDA_ExtHelp = NULL;
1057 rdargs->RDA_Flags = 0;
1059 if (prefixindex < 0)
1060 parser = addndbent; /* no prefix */
1061 else
1062 parser = ndb_parse_funs[prefixindex];
1064 while (FGets(fh, buf, CONFIGLINELEN - 1)) {
1065 line++; /* maintain line number */
1066 /* pass by white space */
1067 for (p = buf; *p == ' ' || *p == '\t' || *p == '\r'; p++)
1069 rdargs->RDA_Source.CS_CurChr = p - buf;
1070 if (*p == '#' || *p == ';' || *p == '\n') /* only a comment line */
1071 continue;
1072 /* remove comments & calc length */
1073 for (; *p; p++) {
1074 if (*p == '#' || *p == ';') {
1075 *p++ = '\n';
1076 *p = '\0'; /* terminate line */
1077 break;
1080 /* ensure that line ends with '\n' (ReadArgs() depends on it) */
1081 if (*(p - 1) != '\n') {
1082 *p++ = '\n';
1083 *p = '\0';
1085 rdargs->RDA_Source.CS_Length = p - buf;
1086 rdargs->RDA_Buffer = NULL;
1087 rdargs->RDA_BufSiz = 0;
1088 #if defined(__AROS__)
1089 D(bug("[AROSTCP](amiga_netdb.c) read_netdb: parsing line: %s, prefixindex=%ld\n", buf, prefixindex));
1090 #endif
1091 DNETDB(Printf("Processing line: %s, prefixindex=%ld\n", buf, prefixindex);)
1092 retval = parser(ndb, rdargs, errstrp, res, flags);
1093 if (retval == RETURN_OK)
1094 continue;
1095 if (retval != RETURN_WARN) { /* severe error */
1096 error_request("Fatal error in NetDB file %s at line %ld, col %ld\n%s\nAROSTCP will quit",
1097 (IPTR)fname, (IPTR)line, (IPTR)rdargs->RDA_Source.CS_CurChr, (IPTR)*errstrp);
1098 break;
1100 /* Log the error */
1101 error_request("Error in NetDB file %s at line %ld, col %ld\n%s",
1102 (IPTR)fname, (IPTR)line, (IPTR)rdargs->RDA_Source.CS_CurChr, (IPTR)*errstrp);
1103 __log(LOG_WARNING, "NetDB(%s) line %ld: %s before col %ld\n",
1104 fname, line, *errstrp, rdargs->RDA_Source.CS_CurChr);
1106 warnval = retval;
1108 /* Check file error */
1109 ioerr = IoErr();
1111 FreeDosObject(DOS_RDARGS, rdargs);
1113 Close(fh);
1114 } else {
1115 ioerr = IoErr();
1118 if (ioerr) {
1119 #if defined(__AROS__)
1120 D(bug("[AROSTCP](amiga_netdb.c) read_netdb: ioerror\n"));
1121 #endif
1122 Fault(ioerr, "readnetdb", res->CS_Buffer, res->CS_Length);
1123 *errstrp = res->CS_Buffer;
1124 retval = RETURN_ERROR;
1126 if ((!fh) && (ndb_Lock.ss_NestCount == 1))
1127 error_request("Unable to open NetDB file %s\n%s", (IPTR)fname, (IPTR)*errstrp);
1129 /* return old current directory */
1130 if (lock) {
1131 CurrentDir(oldcd);
1132 UnLock(lock);
1135 FreeMem(buf, CONFIGLINELEN);
1136 } else {
1137 #if defined(__AROS__)
1138 D(bug("[AROSTCP](amiga_netdb.c) read_netdb: Failed to allocate buffer\n"));
1139 #endif
1140 *errstrp = ERR_MEMORY;
1141 retval = RETURN_FAIL;
1144 UNLOCK_NDB(ndb);
1146 return retval > warnval? retval: warnval;
1150 * Parse the 'ADD' command
1152 LONG
1153 do_netdb(struct CSource *csarg, UBYTE **errstrp, struct CSource *res)
1155 struct RDArgs *rdargs;
1156 LONG retval;
1158 #if defined(__AROS__)
1159 D(bug("[AROSTCP](amiga_netdb.c) do_netdb()\n"));
1160 #endif
1162 if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) {
1163 /* initialize CSource of the rdargs */
1164 rdargs->RDA_Source = *csarg;
1165 /* initialize rest fields (see <dos/rdargs.h>) */
1166 rdargs->RDA_DAList = 0;
1167 rdargs->RDA_Buffer = NULL;
1168 rdargs->RDA_BufSiz = 0;
1169 rdargs->RDA_ExtHelp = NULL;
1170 rdargs->RDA_Flags = 0;
1172 LOCK_W_NDB(NDB);
1174 retval = addndbent(NDB, rdargs, errstrp, res, 0);
1175 /* TODO: set flags here */
1177 UNLOCK_NDB(NDB);
1179 FreeDosObject(DOS_RDARGS, rdargs);
1181 else
1182 retval = RETURN_FAIL;
1184 return retval;
1188 * Initialize the Network Data Base
1190 LONG
1191 init_netdb(void)
1193 UBYTE result[REPLYBUFLEN + 1]; /* for error returns */
1194 struct CSource res;
1195 UBYTE *errstr;
1196 LONG retval;
1198 #if defined(__AROS__)
1199 D(bug("[AROSTCP](amiga_netdb.c) init_netdb()\n"));
1200 #endif
1202 res.CS_Buffer = result;
1203 res.CS_Length = sizeof (result);
1204 res.CS_CurChr = 0;
1206 InitSemaphore (&ndb_Lock);
1207 InitSemaphore (&DynDB.dyn_Lock);
1208 NewList((struct List *)&DynDB.dyn_NameServers);
1209 NewList((struct List *)&DynDB.dyn_Domains);
1210 ndb_Serial = 0;
1212 /* Allocate the NetDataBase */
1213 if (!(NDB = alloc_netdb(NULL))) {
1214 return RETURN_FAIL;
1217 /* Read in the default data base file */
1218 retval = read_netdb(NDB, netdbname, &errstr, &res, -1, NETDB_IFF_ADDNEW);
1219 /* if (retval) {
1220 Printf("init_netdb: file %s: %s\n", netdbname, errstr);
1221 __log(LOG_WARNING, "init_netdb: file %s: %s", netdbname, errstr);
1222 } else */
1223 if (retval == RETURN_WARN)
1224 retval = RETURN_OK;
1226 if (!retval)
1227 setup_accesscontroltable(NDB);
1229 return retval;
1233 void netdb_deinit(void)
1235 #if defined(__AROS__)
1236 D(bug("[AROSTCP](amiga_netdb.c) netdb_deinit()\n"));
1237 #endif
1238 /* A Placeholder for possible future deinitializations */
1242 * Reset the NetDataBase
1244 LONG reset_netdb(struct CSource *cs,
1245 UBYTE **errstrp,
1246 struct CSource *res)
1248 LONG retval;
1249 struct NetDataBase *newnetdb;
1251 #if defined(__AROS__)
1252 D(bug("[AROSTCP](amiga_netdb.c) reset_netdb()\n"));
1253 #endif
1255 /* Allocate a temporary NetDataBase */
1256 if (!(newnetdb = alloc_netdb(NULL))) {
1257 *errstrp = ERR_MEMORY;
1258 return RETURN_FAIL;
1261 retval = read_netdb(newnetdb, netdbname, errstrp, res, -1, 0);
1262 /* TODO: set flags here */
1264 if (retval == RETURN_OK) {
1265 setup_accesscontroltable(newnetdb);
1267 /* Now clear the old lists of the NDB */
1268 LOCK_W_NDB(NDB);
1270 free_netdb(NDB);
1271 NDB = newnetdb;
1273 UNLOCK_NDB(NDB);
1274 ndb_Serial++;
1275 } else {
1276 free_netdb(newnetdb);
1279 return retval;