From 8c62dddd3897439bbb9ad5dc897ca48a1c7b3a4d Mon Sep 17 00:00:00 2001 From: patthoyts Date: Tue, 4 Mar 2003 01:58:26 +0000 Subject: [PATCH] Added support for symbolic port names. --- ChangeLog | 2 ++ generic/udp_tcl.c | 61 ++++++++++++++++++++++++++++++++++++----------- tests/udp.test | 36 +++++++++++++++++++++++++--- 3 files changed, 82 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 95e69a2..f6f08d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,8 @@ * generic/udp_tcl.c: Fix include list to use the autoconfig test results. Fixes for CONST Tcl 8.3/8.4 compatability. + * genetic/udp_tcl.c: Enhanced udp_open and udp_conf to permit the + use of symbolic port names. Added some tests for this. 2003-02-27 Pat Thoyts diff --git a/generic/udp_tcl.c b/generic/udp_tcl.c index 0358c36..89605b3 100644 --- a/generic/udp_tcl.c +++ b/generic/udp_tcl.c @@ -67,6 +67,8 @@ static int udpOutput(ClientData instanceData, CONST84 char *buf, int toWrite, in static int udpInput(ClientData instanceData, char *buf, int bufSize, int *errorCode); static int udpClose(ClientData instanceData, Tcl_Interp *interp); static void udpTrace(const char *format, ...); +static int udpGetService(Tcl_Interp *interp, const char *service, + unsigned short *servicePort); #ifdef WIN32 static HANDLE waitForSock; @@ -253,13 +255,13 @@ udpConf(ClientData clientData, Tcl_Interp *interp, if (argc == 3) { if (!strcmp(argv[2], "-myport")) { - sprintf(buf, "%d", statePtr->localport); + sprintf(buf, "%d", ntohs(statePtr->localport)); Tcl_AppendResult(interp, buf, (char *)NULL); } else if (!strcmp(argv[2], "-remote")) { if (statePtr->remotehost && *statePtr->remotehost) { sprintf(buf, "%s", statePtr->remotehost); Tcl_AppendResult(interp, buf, (char *)NULL); - sprintf(buf, "%d", statePtr->remoteport); + sprintf(buf, "%d", ntohs(statePtr->remoteport)); Tcl_AppendElement(interp, buf); } } else if (!strcmp(argv[2], "-peer")) { @@ -326,8 +328,7 @@ udpConf(ClientData clientData, Tcl_Interp *interp, return TCL_ERROR; } strcpy(statePtr->remotehost, argv[2]); - statePtr->remoteport = atoi(argv[3]); - return TCL_OK; + return udpGetService(interp, argv[3], &(statePtr->remoteport)); } } else { result = "udpConf fileId [-mcastadd] [-mcastdrop] groupaddr | udpConf fileId remotehost remoteport | udpConf fileId [-myport] [-remote] [-peer]"; @@ -521,7 +522,8 @@ udpOpen(ClientData clientData, Tcl_Interp *interp, Udp_ChannelType->close2Proc = NULL; if (argc >= 2) { - localport = atoi(argv[1]); + if (udpGetService(interp, argv[1], &localport) != TCL_OK) + return TCL_ERROR; } memset(channelName, 0, sizeof(channelName)); @@ -540,11 +542,11 @@ udpOpen(ClientData clientData, Tcl_Interp *interp, memset(&addr, 0, sizeof(addr)); #ifdef SIPC_IPV6 addr.sin6_family = AF_INET6; - addr.sin6_port = htons(localport); + addr.sin6_port = localport; #else addr.sin_family = AF_INET; addr.sin_addr.s_addr = 0; - addr.sin_port = htons(localport); + addr.sin_port = localport; #endif if (bind(sock,(struct sockaddr *)&addr, sizeof(addr)) < 0) { sprintf(errBuf,"%s","udp - bind"); @@ -561,13 +563,14 @@ udpOpen(ClientData clientData, Tcl_Interp *interp, len = sizeof(sockaddr); getsockname(sock, (struct sockaddr *)&sockaddr, &len); #ifdef SIPC_IPV6 - localport = ntohs(sockaddr.sin6_port); + localport = sockaddr.sin6_port; #else - localport = ntohs(sockaddr.sin_port); + localport = sockaddr.sin_port; #endif } - UDPTRACE("Open socket %d. Bind socket to port %d\n", sock, localport); + UDPTRACE("Open socket %d. Bind socket to port %d\n", + sock, ntohs(localport)); statePtr = (UdpState *) ckalloc((unsigned) sizeof(UdpState)); memset(statePtr, 0, sizeof(UdpState)); @@ -845,12 +848,12 @@ udpOutput(ClientData instanceData, CONST84 char *buf, int toWrite, int *errorCod memcpy(&sendaddr.sin6_addr, name->h_addr, sizeof(sendaddr.sin6_addr)); } sendaddr.sin6_family = AF_INET6; - sendaddr.sin6_port = htons(statePtr->remoteport); + sendaddr.sin6_port = statePtr->remoteport; #else memcpy(&sendaddr.sin_addr, name->h_addr, sizeof(sendaddr.sin_addr)); } sendaddr.sin_family = AF_INET; - sendaddr.sin_port = htons(statePtr->remoteport); + sendaddr.sin_port = statePtr->remoteport; #endif written = sendto(statePtr->sock, buf, toWrite, 0, (struct sockaddr *)&sendaddr, socksize); @@ -859,8 +862,8 @@ udpOutput(ClientData instanceData, CONST84 char *buf, int toWrite, int *errorCod return -1; } - UDPTRACE("Send %d to %s:%d through %d\n", written, - statePtr->remotehost, statePtr->remoteport, statePtr->sock); + UDPTRACE("Send %d to %s:%d through %d\n", written, statePtr->remotehost, + ntohs(statePtr->remoteport), statePtr->sock); return written; } @@ -1002,3 +1005,33 @@ udpTrace(const char *format, ...) va_end(args); } + +/* + * Return the service port number in network byte order from either a string + * representation of the port number or the service name. If the service + * string cannot be converted (ie: a name not present in the services + * database) then set a Tcl error. + */ +static int +udpGetService(Tcl_Interp *interp, const char *service, + unsigned short *servicePort) +{ + struct servent *sv = NULL; + char *remainder = NULL; + int r = TCL_OK; + + sv = getservbyname(service, "udp"); + if (sv != NULL) { + *servicePort = sv->s_port; + } else { + *servicePort = htons((unsigned short)strtol(service, &remainder, 0)); + if (remainder == service) { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "invalid service name: \"", service, + "\" could not be converted to a port number", + TCL_STATIC); + r = TCL_ERROR; + } + } + return r; +} diff --git a/tests/udp.test b/tests/udp.test index 8dc2eae..ad900e6 100644 --- a/tests/udp.test +++ b/tests/udp.test @@ -39,13 +39,13 @@ test udp_1.3 {close udp socket} { test udp-1.4 {udp_open on assigned port} { list [catch { - set port 53530 + set port 0xf0b0 set s [udp_open $port] set check [udp_conf $s -myport] close $s - expr {$port == $check} + format 0x%04x $check } msg] $msg -} {0 1} +} {0 0xf0b0} test udp-1.5 {udp_conf -remote before seting remote details} { list [catch { @@ -65,6 +65,36 @@ test udp-1.6 {udp_conf -peer before setting remote details} { } msg] $msg } {0 {}} + +test udp-2.0 {udp_conf using service name} { + list [catch { + set s [udp_open] + udp_conf $s localhost ntp + set r [udp_conf $s -remote] + close $s + set r} msg] $msg +} {0 {localhost 123}} + +test udp-2.1 {udp_conf using service number} { + list [catch { + set s [udp_open] + udp_conf $s localhost 123 + set r [udp_conf $s -remote] + close $s + set r} msg] $msg +} {0 {localhost 123}} + +test udp-2.2 {udp_open on named port} { + list [catch { + set port ntp + set s [udp_open $port] + set check [udp_conf $s -myport] + close $s + format 0x%04x $check + } msg] $msg +} {0 0x007b} + + # ------------------------------------------------------------------------- # cleanup catch {unset _udp} -- 2.23.0