URL
https://opencores.org/ocsvn/or1k_old/or1k_old/trunk
Subversion Repositories or1k_old
[/] [or1k_old/] [trunk/] [uclinux/] [userland/] [route/] [lib/] [inet.c] - Rev 1782
Compare with Previous | Blame | View Log
/* * lib/inet.c This file contains an implementation of the "INET" * support functions for the net-tools. * (NET-3 base distribution). * * Version: $Id: inet.c,v 1.1 2002-03-17 19:58:53 simons Exp $ * * Author: Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> * Copyright 1993 MicroWalt Corporation * * Modified: *960113 {1.21} Bernd Eckenfels : rresolve cache bug. *960128 {1.22} Bernd Eckenfels : endian bug in print *960203 {1.23} Bernd Eckenfels : net-features support *960217 {1.24} Bernd Eckenfels : get_sname *960219 {1.25} Bernd Eckenfels : extern int h_errno *960329 {1.26} Bernd Eckenfels : resolve 255.255.255.255 *980101 {1.27} Bernd Eckenfels : resolve raw sockets in /etc/protocols *990302 {1.28} Phil Blundell : add netmask to INET_rresolve * * This program is free software; you can redistribute it * and/or modify it under the terms of the GNU General * Public License as published by the Free Software * Foundation; either version 2 of the License, or (at * your option) any later version. */ #include "config.h" /* FIXME. Split this file into inet4.c for the IPv4 specific parts and inet.c for those shared between IPv4 and IPv6. */ #if HAVE_AFINET || HAVE_AFINET6 #include <netinet/in.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <arpa/nameser.h> #include <ctype.h> #include <errno.h> #include <netdb.h> #include <resolv.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <unistd.h> #include "version.h" #include "net-support.h" #include "pathnames.h" #include "intl.h" #include "util.h" extern int h_errno; /* some netdb.h versions don't export this */ struct addr { struct sockaddr_in addr; char *name; struct addr *next; }; struct service { int number; char *name; struct service *next; }; static struct service *tcp_name = NULL, *udp_name = NULL, *raw_name = NULL; #if HAVE_AFINET static struct addr *INET_nn = NULL; /* addr-to-name cache */ static int INET_resolve(char *name, struct sockaddr_in *sin) { struct hostent *hp; struct netent *np; /* Grmpf. -FvK */ sin->sin_family = AF_INET; sin->sin_port = 0; /* Default is special, meaning 0.0.0.0. */ if (!strcmp(name, "default")) { sin->sin_addr.s_addr = INADDR_ANY; return (1); } /* Look to see if it's a dotted quad. */ if (inet_aton(name, &sin->sin_addr)) { return 0; } #ifdef EMBED return(-1); #else /* Try the NETWORKS database to see if this is a known network. */ if ((np = getnetbyname(name)) != (struct netent *) NULL) { sin->sin_addr.s_addr = htonl(np->n_net); strcpy(name, np->n_name); return 1; } #ifdef DEBUG res_init(); _res.options |= RES_DEBUG; #endif if ((hp = gethostbyname(name)) == (struct hostent *) NULL) { errno = h_errno; return -1; } memcpy((char *) &sin->sin_addr, (char *) hp->h_addr_list[0], hp->h_length); strcpy(name, hp->h_name); return 0; #endif } static int INET_rresolve(char *name, struct sockaddr_in *sin, int numeric, unsigned int netmask) { struct hostent *ent; struct netent *np; struct addr *pn; unsigned long ad, host_ad; /* Grmpf. -FvK */ if (sin->sin_family != AF_INET) { #ifdef DEBUG fprintf(stderr, _("rresolve: unsupport address family %d !\n"), sin->sin_family); #endif errno = EAFNOSUPPORT; return (-1); } ad = (unsigned long) sin->sin_addr.s_addr; if (ad == INADDR_ANY) { if ((numeric & 0x7FFF) == 0) { if (numeric & 0x8000) strcpy(name, "default"); else strcpy(name, "*"); return (0); } } if (numeric & 0x7FFF) { strcpy(name, inet_ntoa(sin->sin_addr)); return (0); } #if 0 INET_nn = NULL; #endif pn = INET_nn; while (pn != NULL) { if (pn->addr.sin_addr.s_addr == ad) { strcpy(name, pn->name); return (0); } pn = pn->next; } host_ad = ntohl(ad); np = NULL; ent = NULL; #ifndef EMBED if ((ad & (~ netmask)) != 0) { ent = gethostbyaddr((char *) &ad, 4, AF_INET); if (ent != NULL) strcpy(name, ent->h_name); } else { np = getnetbyaddr(host_ad, AF_INET); if (np != NULL) { strcpy(name, np->n_name); } } #endif if ((ent == NULL) && (np == NULL)) { strcpy(name, inet_ntoa(sin->sin_addr)); } pn = (struct addr *) malloc(sizeof(struct addr)); pn->addr = *sin; pn->next = INET_nn; pn->name = (char *) malloc(strlen(name) + 1); strcpy(pn->name, name); INET_nn = pn; return (0); } static void INET_reserror(char *text) { #ifdef EMBED printf(text); #else herror(text); #endif } /* Display an Internet socket address. */ static char *INET_print(unsigned char *ptr) { return (inet_ntoa((*(struct in_addr *) ptr))); } /* Display an Internet socket address. */ static char *INET_sprint(struct sockaddr *sap, int numeric) { static char buff[128]; if (sap->sa_family == 0xFFFF || sap->sa_family == 0) return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff)); if (INET_rresolve(buff, (struct sockaddr_in *) sap, numeric, 0xffffff00) != 0) return (NULL); return (buff); } char *INET_sprintmask(struct sockaddr *sap, int numeric, unsigned int netmask) { static char buff[128]; if (sap->sa_family == 0xFFFF || sap->sa_family == 0) return safe_strncpy(buff, _("[NONE SET]"), sizeof(buff)); if (INET_rresolve(buff, (struct sockaddr_in *) sap, numeric, netmask) != 0) return (NULL); return (buff); } static int INET_getsock(char *bufp, struct sockaddr *sap) { char *sp = bufp, *bp; unsigned int i; unsigned val; struct sockaddr_in *sin; sin = (struct sockaddr_in *) sap; sin->sin_family = AF_INET; sin->sin_port = 0; val = 0; bp = (char *) &val; for (i = 0; i < sizeof(sin->sin_addr.s_addr); i++) { *sp = toupper(*sp); if ((*sp >= 'A') && (*sp <= 'F')) bp[i] |= (int) (*sp - 'A') + 10; else if ((*sp >= '0') && (*sp <= '9')) bp[i] |= (int) (*sp - '0'); else return (-1); bp[i] <<= 4; sp++; *sp = toupper(*sp); if ((*sp >= 'A') && (*sp <= 'F')) bp[i] |= (int) (*sp - 'A') + 10; else if ((*sp >= '0') && (*sp <= '9')) bp[i] |= (int) (*sp - '0'); else return (-1); sp++; } sin->sin_addr.s_addr = htonl(val); return (sp - bufp); } static int INET_input(int type, char *bufp, struct sockaddr *sap) { switch (type) { case 1: return (INET_getsock(bufp, sap)); default: return (INET_resolve(bufp, (struct sockaddr_in *) sap)); } } static int INET_getnetmask(char *adr, struct sockaddr *m, char *name) { struct sockaddr_in *mask = (struct sockaddr_in *) m; char *slash, *end; int prefix; if ((slash = strchr(adr, '/')) == NULL) return 0; *slash++ = '\0'; prefix = strtoul(slash, &end, 0); if (*end != '\0') return -1; if (name) { sprintf(name, "/%d", prefix); } mask->sin_family = AF_INET; mask->sin_addr.s_addr = htonl(~(0xffffffffU >> prefix)); return 1; } struct aftype inet_aftype = { "inet", NULL, /*"DARPA Internet", */ AF_INET, sizeof(unsigned long), INET_print, INET_sprint, INET_input, INET_reserror, NULL /*INET_rprint */ , NULL /*INET_rinput */ , INET_getnetmask, -1, NULL }; #endif /* HAVE_AFINET */ static void add2list(struct service **namebase, struct service *item) { if (*namebase == NULL) { *namebase = item; item->next = NULL; } else { item->next = *namebase; *namebase = item; } } static struct service *searchlist(struct service *servicebase, int number) { struct service *item; for (item = servicebase; item != NULL; item = item->next) { if (item->number == number) return (item); } return (NULL); } #ifndef EMBED static int read_services(void) { struct servent *se; struct protoent *pe; struct service *item; setservent(1); while ((se = getservent())) { /* Allocate a service entry. */ item = (struct service *) malloc(sizeof(struct service)); if (item == NULL) perror("netstat"); item->name = strdup(se->s_name); item->number = se->s_port; /* Fill it in. */ if (!strcmp(se->s_proto, "tcp")) { add2list(&tcp_name, item); } else if (!strcmp(se->s_proto, "udp")) { add2list(&udp_name, item); } else if (!strcmp(se->s_proto, "raw")) { add2list(&raw_name, item); } } endservent(); setprotoent(1); while ((pe = getprotoent())) { /* Allocate a service entry. */ item = (struct service *) malloc(sizeof(struct service)); if (item == NULL) perror("netstat"); item->name = strdup(pe->p_name); item->number = htons(pe->p_proto); add2list(&raw_name, item); } endprotoent(); return (0); } #endif char *get_sname(int socknumber, char *proto, int numeric) { static char buffer[64], init = 0; struct service *item; if (socknumber == 0) return ("*"); if (numeric) { sprintf(buffer, "%d", ntohs(socknumber)); return (buffer); } #ifndef EMBED if (!init) { (void) read_services(); init = 1; } #endif buffer[0] = '\0'; if (!strcmp(proto, "tcp")) { if ((item = searchlist(tcp_name, socknumber)) != NULL) sprintf(buffer, "%s", item->name); } else if (!strcmp(proto, "udp")) { if ((item = searchlist(udp_name, socknumber)) != NULL) sprintf(buffer, "%s", item->name); } else if (!strcmp(proto, "raw")) { if ((item = searchlist(raw_name, socknumber)) != NULL) sprintf(buffer, "%s", item->name); } if (!buffer[0]) sprintf(buffer, "%d", ntohs(socknumber)); return (buffer); } #endif /* HAVE_AFINET || HAVE_AFINET6 */