#ifndef LINT static char *rcsid="$Id: serv_udp.c,v 1.8 1999/10/03 21:18:04 crosser Exp $"; #endif /* $Log: serv_udp.c,v $ Revision 1.8 1999/10/03 21:18:04 crosser First (probably) working version with new run time config parser. Also added listenq parameter (backlog size for listen()) and renamed wtest to whoson (and with man page). Release 2.00beta1. Revision 1.7 1999/08/19 17:22:16 crosser Move to new config scheme (does not work yet) Revision 1.6 1998/07/28 17:51:53 crosser make 64bit architecure happy Revision 1.5 1998/07/26 14:06:40 crosser change due to checkperm names Revision 1.4 1998/07/05 00:26:18 crosser Change copyright Revision 1.3 1998/07/02 18:01:15 crosser change error reporting to syslog Revision 1.2 1998/07/02 15:37:07 crosser make right responce if req invalid Revision 1.1 1998/07/01 21:55:16 crosser Initial revision Revision 1.3 1998/07/01 08:04:58 crosser stylistic Revision 1.2 1998/07/01 05:18:09 crosser minor warnings fix Revision 1.1 1998/07/01 05:01:22 crosser Initial revision */ /* WHAT IS IT: Implementation of experimental "whoson" protocol AUTHOR: Eugene G. Crosser COPYRIGHT: Public domain */ #include "config.h" #include #include #include #include #include #include #include #include #include #ifdef HAVE_SYS_SELECT_H #include #endif #include #include #include #include #include #include #include "whosond.h" #include "rtconfig.h" #include "serv_common.h" #include "checkperm.h" #include "report.h" #include "rtc_begin.h" #include "serv_udp_cfg.h" #include "rtc_middle.h" #include "serv_udp_cfg.h" #include "rtc_end.h" struct _udp_data_rec { struct _perm *perms; char buf[512]; }; static struct _evdesc udp_read_evproc(int fd,void *priv) { struct _udp_data_rec *data=(struct _udp_data_rec *)priv; struct _evdesc evdesc; int len,slen; struct sockaddr_in frominet; char retbuf[512]; DPRINT(("udp_read_evproc(%d,%p)\n",fd,priv)) memset(&evdesc,0,sizeof(struct _evdesc)); evdesc.fd=-1; if (fd < 0) { fd=-fd; close(fd); free(data); } else { slen = sizeof(frominet); if ((len=recvfrom(fd,data->buf,sizeof(data->buf)-1, 0,(struct sockaddr *)&frominet,&slen)) > 0) { DPRINT(("UDP message (%d bytes) from %s\n",len,inet_ntoa(frominet.sin_addr))) retbuf[0]='\0'; if (wso_perm_check(data->perms, ntohl(frominet.sin_addr.s_addr))) do_request(data->buf,retbuf,sizeof(retbuf)); else strcpy(retbuf,NOPERM); len=strlen(retbuf); slen = sizeof(frominet); if (sendto(fd,retbuf,len,0, (struct sockaddr *)&frominet,slen) != len) { ERRLOG((LOG_ERR,"sendto: %m")) } } else { ERRLOG((LOG_ERR,"recvfrom: %m")) } } DPRINT(("udp_read_evproc returns fd=%d evproc=%p\n",evdesc.fd,evdesc.evproc)) return evdesc; } struct _evdesc udp_serv_init(void *priv) { wso_serv_udp_cfg *rec=(wso_serv_udp_cfg *)priv; struct _evdesc evdesc; struct _udp_data_rec *data; struct sockaddr_in server; struct protoent *proto; int protonum; int msgsock=-1; int tries,on=1; DPRINT(("udp_serv_init(%p)\n",priv)) memset((char *)&server,0,sizeof(server)); server.sin_family = AF_INET; if ((proto=getprotobyname("udp"))) protonum=proto->p_proto; else protonum=17; server.sin_port=htons(rec->port); server.sin_addr.s_addr=INADDR_ANY; if ((msgsock=socket(AF_INET,SOCK_DGRAM,protonum)) < 0) { ERRLOG((LOG_ERR,"socket: %m")) goto exit; } if (setsockopt(msgsock,SOL_SOCKET,SO_REUSEADDR, (char*)&on,sizeof(on)) < 0) { ERRLOG((LOG_ERR,"setsockopt: %m")) msgsock=-1; goto exit; } for (tries=0;;tries++) { if (bind(msgsock,(struct sockaddr*)&server, sizeof(server)) < 0) { if ((errno == EADDRINUSE) && (tries < 10)) { sleep(tries); continue; } ERRLOG((LOG_ERR,"bind: %m")) msgsock=-1; goto exit; } else break; } exit: memset(&evdesc,0,sizeof(struct _evdesc)); evdesc.fd=msgsock; evdesc.evproc=udp_read_evproc; evdesc.ttl=0; evdesc.priv=priv; if ((data=(struct _udp_data_rec *)malloc (sizeof(struct _udp_data_rec)))) { memset(data,0,sizeof(struct _udp_data_rec)); data->perms=rec->perms; evdesc.priv=data; } else { ERRLOG((LOG_ERR,"allocating struct _udp_data_rec: %m")) evdesc.fd=-1; evdesc.evproc=NULL; } DPRINT(("udp_serv_init returns fd=%d evproc=%p\n",evdesc.fd,evdesc.evproc)) return evdesc; }