* generic/udp_tcl.c: Added support for setting and retrieving the
authorpatthoyts <patthoyts>
Mon, 22 Nov 2004 10:00:30 +0000 (10:00 +0000)
committerpatthoyts <patthoyts>
Mon, 22 Nov 2004 10:00:30 +0000 (10:00 +0000)
  TTL option on the socket. The default is specified by the system
  but can be set for individual sockets.

ChangeLog
generic/udp_tcl.c

index df04053f03bfa33196340e42dbba0a0cfb122094..c86949e9331ccec0f198789c21e9f95e25cd09c8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2004-11-22  Pat Thoyts  <pat@zsplat.freeserve.co.uk>
+
+       * generic/udp_tcl.c: Added support for setting and retrieving the
+       TTL option on the socket. The default is specified by the system
+       but can be set for individual sockets. 
+
 2004-02-09  Pat Thoyts  <patthoyts@users.sourceforge.net>
 
        * generic/udp_tcl.c: Followed up a suggestion in patch #794072 to
index 1ef237bae9a750c5af5c5dfe1984a3448669831a..8fc25f27acd5323bafa584fbaaba796b5082376d 100644 (file)
@@ -312,10 +312,13 @@ udpConf(ClientData clientData, Tcl_Interp *interp,
     struct ip_mreq mreq;
     struct sockaddr_in maddr;
     int sock;
+    char errmsg[] = 
+      "udpConf fileId [-mcastadd] [-mcastdrop] groupaddr | "
+      "udpConf fileId remotehost remoteport | "
+      "udpConf fileId [-myport] [-remote] [-peer] [-broadcast] [-ttl]";
     
     if (argc != 4 && argc != 3) {
-        result = "udpConf fileId [-mcastadd] [-mcastdrop] groupaddr | udpConf fileId remotehost remoteport | udpConf fileId [-myport] [-remote] [-peer] [-broadcast]";
-        Tcl_SetResult (interp, result, NULL);
+        Tcl_SetResult (interp, errmsg, NULL);
         return TCL_ERROR;
     }
     chan = Tcl_GetChannel(interp, (char *)argv[1], NULL);
@@ -348,8 +351,21 @@ udpConf(ClientData clientData, Tcl_Interp *interp,
             socklen_t optlen = sizeof(int);
             if (getsockopt(statePtr->sock, SOL_SOCKET, SO_BROADCAST, 
                            (char *)&tmp, &optlen)) {
-                sprintf(errBuf, "%s", "udp - setsockopt");
-                UDPTRACE("UDP error - setsockopt\n");
+                sprintf(errBuf, "%s", "udp - getsockopt");
+                UDPTRACE("UDP error - getsockopt\n");
+                Tcl_AppendResult(interp, errBuf, (char *)NULL);
+                return TCL_ERROR;
+            } else {
+                Tcl_SetObjResult(interp, Tcl_NewIntObj(tmp));
+                return TCL_OK;
+            }
+        } else if (!strcmp(argv[2], "-ttl")) {
+            int tmp = 1;
+            socklen_t optlen = sizeof(int);
+            if (getsockopt(statePtr->sock, SOL_IP, IP_TTL, 
+                           (char *)&tmp, &optlen)) {
+                sprintf(errBuf, "%s", "udp - getsockopt");
+                UDPTRACE("UDP error - getsockopt\n");
                 Tcl_AppendResult(interp, errBuf, (char *)NULL);
                 return TCL_ERROR;
             } else {
@@ -357,8 +373,7 @@ udpConf(ClientData clientData, Tcl_Interp *interp,
                 return TCL_OK;
             }
         } else {
-            result = "udpConf fileId [-mcastadd] [-mcastdrop] groupaddr | udpConf fileId remotehost remoteport | udpConf fileId [-myport] [-remote] [-peer]";
-            Tcl_SetResult (interp, result, NULL);
+            Tcl_SetResult (interp, errmsg, NULL);
             return TCL_ERROR;
         }
         return TCL_OK;
@@ -422,6 +437,22 @@ udpConf(ClientData clientData, Tcl_Interp *interp,
                 }
             }
             return r;
+        } else if (!strcmp(argv[2], "-ttl")) {
+            socklen_t optlen = sizeof(int);
+            int tmp = 0;
+            int r = Tcl_GetInt(interp, argv[3], &tmp);
+            if (r == TCL_OK) {
+                if (setsockopt(statePtr->sock, SOL_IP, IP_TTL,
+                               (const char *)&tmp, optlen)) {
+                    sprintf(errBuf, "%s", "udp - setsockopt");
+                    UDPTRACE("UDP error - setsockopt\n");
+                    Tcl_AppendResult(interp, errBuf, (char *)NULL);
+                    r = TCL_ERROR;
+                } else {
+                    Tcl_SetObjResult(interp, Tcl_NewIntObj(tmp));
+                }
+            }
+            return r;
         } else {
             if (strlen(argv[2]) >= sizeof(statePtr->remotehost)) {
                 result = "hostname too long";
@@ -432,8 +463,7 @@ udpConf(ClientData clientData, Tcl_Interp *interp,
             return udpGetService(interp, argv[3], &(statePtr->remoteport));
         }
     } else {
-        result = "udpConf fileId [-mcastadd] [-mcastdrop] groupaddr | udpConf fileId remotehost remoteport | udpConf fileId [-myport] [-remote] [-peer]";
-        Tcl_SetResult (interp, result, NULL);
+        Tcl_SetResult (interp, errmsg, NULL);
         return TCL_ERROR;
     }
 }
@@ -1125,7 +1155,7 @@ udpGetOption(ClientData instanceData, Tcl_Interp *interp,
              CONST84 char *optionName, Tcl_DString *optionValue)
 {
     UdpState *statePtr = (UdpState *)instanceData;
-    CONST84 char * options = "myport remote peer mcastadd mcastdrop";
+    CONST84 char * options = "myport remote peer mcastadd mcastdrop broadcast ttl";
     int r = TCL_OK;
 
     if (optionName == NULL) {
@@ -1142,6 +1172,8 @@ udpGetOption(ClientData instanceData, Tcl_Interp *interp,
         udpGetOption(instanceData, interp, "-mcastdrop", optionValue);
         Tcl_DStringAppend(optionValue, " -broadcast ", -1);
         udpGetOption(instanceData, interp, "-broadcast", optionValue);
+        Tcl_DStringAppend(optionValue, " -ttl ", -1);
+        udpGetOption(instanceData, interp, "-ttl", optionValue);
 
     } else {
 
@@ -1179,14 +1211,28 @@ udpGetOption(ClientData instanceData, Tcl_Interp *interp,
             socklen_t optlen = sizeof(int);
             if (getsockopt(statePtr->sock, SOL_SOCKET, SO_BROADCAST, 
                            (char *)&tmp, &optlen)) {
-                UDPTRACE("UDP error - setsockopt\n");
-                Tcl_SetResult(interp, "error in setsockopt", TCL_STATIC);
+                UDPTRACE("UDP error - getsockopt\n");
+                Tcl_SetResult(interp, "error in getsockopt", TCL_STATIC);
                 r = TCL_ERROR;
             } else {
                 Tcl_DStringSetLength(&ds, TCL_INTEGER_SPACE);
                 sprintf(Tcl_DStringValue(&ds), "%d", tmp);
             }
 
+        } else if (!strcmp("-ttl", optionName)) {
+          
+            unsigned int tmp = 0;
+            socklen_t optlen = sizeof(unsigned int);
+            if (getsockopt(statePtr->sock, SOL_IP, IP_TTL,
+                           (char *)&tmp, &optlen)) {
+                UDPTRACE("UDP error - getsockopt");
+                Tcl_SetResult(interp, "error in getsockopt", TCL_STATIC);
+                r = TCL_ERROR;
+            } else {
+                Tcl_DStringSetLength(&ds, TCL_INTEGER_SPACE);
+                sprintf(Tcl_DStringValue(&ds), "%u", tmp);
+            }
+
         } else {
             r = Tcl_BadChannelOption(interp, optionName, options);
         }
@@ -1214,7 +1260,7 @@ udpSetOption(ClientData instanceData, Tcl_Interp *interp,
              CONST84 char *optionName, CONST84 char *newValue)
 {
     UdpState *statePtr = (UdpState *)instanceData;
-    CONST84 char * options = "remote mcastadd mcastdrop broadcast";
+    CONST84 char * options = "remote mcastadd mcastdrop broadcast ttl";
     int r = TCL_OK;
 
     if (!strcmp("-remote", optionName)) {
@@ -1267,6 +1313,21 @@ udpSetOption(ClientData instanceData, Tcl_Interp *interp,
                 Tcl_SetObjResult(interp, Tcl_NewIntObj(tmp));
             }
         }
+    } else if (!strcmp("-ttl", optionName)) {
+
+        unsigned int tmp = 0;
+        r = Tcl_GetInt(interp, newValue, &tmp);
+        if (r == TCL_OK) {
+            if (setsockopt(statePtr->sock, SOL_IP, IP_TTL,
+                           (const char *)&tmp, sizeof(unsigned int))) {
+                sprintf(errBuf, "udp - setsockopt ttl");
+                UDPTRACE("UDP error - setsockopt\n");
+                Tcl_SetObjResult(interp, Tcl_NewStringObj(errBuf, -1));
+                r = TCL_ERROR;
+            } else {
+                Tcl_SetObjResult(interp, Tcl_NewIntObj(tmp));
+            }
+        }
 
     } else {