--- pump-0.8.24/config.c +++ pump-0.8.24/config.c @@ -155,15 +155,26 @@ } override->numRetries = num; - } else if (!strcmp(start, "domainsearch")) { - size_t len; + } else if (!strcmp(start, "routemetric")) { + poptParseArgvString(rest, &argc, &argv); - if (overrideList != override) { - parseError(*lineNum, "domainsearch directive may not occur " - "inside of device specification"); + if (argc != 1) { + parseError(*lineNum, "routemetric directive expects a " + "single argument"); return 1; } + num = strtol(argv[0], &chptr, 0); + if (*chptr) { + parseError(*lineNum, "routemetric requires a numeric " + "argument"); + return 1; + } + + override->routeMetric = num; + } else if (!strcmp(start, "domainsearch")) { + size_t len; + poptParseArgvString(rest, &argc, &argv); if (argc != 1) { @@ -209,6 +220,12 @@ return 1; } override->flags |= OVERRIDE_FLAG_NONISDOMAIN; + } else if (!strcmp(start, "nontp")) { + if (*rest) { + parseError(*lineNum, "unexpected argument to nontp directive"); + return 1; + } + override->flags |= OVERRIDE_FLAG_NONTP; } else if (!strcmp(start, "nosetup")) { if (*rest) { parseError(*lineNum, "unexpected argument to nosetup directive"); @@ -228,12 +245,6 @@ } else if (!strcmp(start, "script")) { size_t len; - if (overrideList != override) { - parseError(*lineNum, "script directive may not occur " - "inside of device specification"); - return 1; - } - poptParseArgvString(rest, &argc, &argv); if (argc != 1) { --- pump-0.8.24/dhcp.c +++ pump-0.8.24/dhcp.c @@ -204,16 +204,30 @@ char * pumpDisableInterface(struct pumpNetIntf * intf) { struct ifreq req; + struct sockaddr_in * addrp; int s; if (intf->flags & PUMP_FLAG_NOSETUP) return NULL; s = socket(AF_INET, SOCK_DGRAM, 0); - - memset(&req,0,sizeof(req)); + memset(&req,0,sizeof(req)); strcpy(req.ifr_name, intf->device); + + addrp = (struct sockaddr_in *) &req.ifr_addr; + addrp->sin_family = AF_INET; + addrp->sin_addr.s_addr = 0; + if (ioctl(s, SIOCSIFADDR, &req)) { + close(s); + return perrorstr("SIOCSIFADDR"); + } + + if (intf->override.flags & OVERRIDE_FLAG_KEEPUP) { + close(s); + return NULL; + } + if (ioctl(s, SIOCGIFFLAGS, &req)) { close(s); return perrorstr("SIOCGIFFLAGS"); @@ -291,18 +305,27 @@ goto out; } - if (!strcmp(intf->device, "lo")) { - /* add a route for this network */ - route.rt_dev = intf->device; - route.rt_flags = RTF_UP; - route.rt_metric = 0; + route.rt_dev = intf->device; + route.rt_flags = RTF_UP; + route.rt_metric = 0; + + addrp->sin_family = AF_INET; + addrp->sin_port = 0; + addrp->sin_addr = intf->network; + memcpy(&route.rt_dst, addrp, sizeof(*addrp)); + addrp->sin_addr = intf->netmask; + memcpy(&route.rt_genmask, addrp, sizeof(*addrp)); + + if (strcmp(intf->device,"lo") && intf->override.routeMetric) { + if (ioctl(s, SIOCDELRT, &route)) { + rc = perrorstr("SIOCDELRT"); + goto out; + } + } - addrp->sin_family = AF_INET; - addrp->sin_port = 0; - addrp->sin_addr = intf->network; - memcpy(&route.rt_dst, addrp, sizeof(*addrp)); - addrp->sin_addr = intf->netmask; - memcpy(&route.rt_genmask, addrp, sizeof(*addrp)); + if (!strcmp(intf->device, "lo") || intf->override.routeMetric) { + if (intf->override.routeMetric) + route.rt_metric = intf->override.routeMetric + 1; if (ioctl(s, SIOCADDRT, &route)) { /* the route cannot already exist, as we've taken the device down */ @@ -316,31 +339,37 @@ return rc; } -int pumpSetupDefaultGateway(struct in_addr * gw) { +int pumpSetupDefaultGateway(struct pumpNetIntf * intf) { struct sockaddr_in addr; struct rtentry route; int s; + int i; s = socket(AF_INET, SOCK_DGRAM, 0); - - memset(&addr,0,sizeof(addr)); - memset(&route,0,sizeof(route)); - addr.sin_family = AF_INET; - addr.sin_port = 0; - addr.sin_addr.s_addr = INADDR_ANY; - memcpy(&route.rt_dst, &addr, sizeof(addr)); - memcpy(&route.rt_genmask, &addr, sizeof(addr)); - addr.sin_addr = *gw; - memcpy(&route.rt_gateway, &addr, sizeof(addr)); - - route.rt_flags = RTF_UP | RTF_GATEWAY; - route.rt_metric = 0; - route.rt_dev = NULL; - if (ioctl(s, SIOCADDRT, &route)) { - close(s); - syslog(LOG_ERR, "failed to set default route: %s", strerror(errno)); - return -1; + for (i = intf->numGateways - 1; i >= 0; i--) { + memset(&addr,0,sizeof(addr)); + memset(&route,0,sizeof(route)); + addr.sin_family = AF_INET; + addr.sin_port = 0; + addr.sin_addr.s_addr = INADDR_ANY; + memcpy(&route.rt_dst, &addr, sizeof(addr)); + memcpy(&route.rt_genmask, &addr, sizeof(addr)); + addr.sin_addr = intf->gateways[i]; + memcpy(&route.rt_gateway, &addr, sizeof(addr)); + + route.rt_flags = RTF_UP | RTF_GATEWAY; + route.rt_dev = intf->device; + if (intf->override.routeMetric) + route.rt_metric = intf->override.routeMetric + 1; + else + route.rt_metric = 0; + + if (ioctl(s, SIOCADDRT, &route)) { + close(s); + syslog(LOG_ERR, "failed to set default route: %s", strerror(errno)); + return -1; + } } close(s); @@ -386,7 +415,7 @@ unsigned char option, length; - chptr = response->vendor; + chptr = (unsigned char *) response->vendor; chptr += 4; while (*chptr != 0xFF) { @@ -463,7 +492,7 @@ intf->set |= PUMP_INTFINFO_HAS_NEXTSERVER; syslog (LOG_DEBUG, "intf: next server: %s", inet_ntoa (intf->nextServer)); - chptr = breq->vendor; + chptr = (unsigned char *) breq->vendor; chptr += 4; while (*chptr != 0xFF && (void *) chptr < (void *) breq->vendor + DHCP_VENDOR_LENGTH) { option = *chptr++; @@ -729,7 +758,7 @@ syslog (LOG_DEBUG, "%s: servername: %s", name, breq->servername); syslog (LOG_DEBUG, "%s: bootfile: %s", name, breq->bootfile); - vndptr = breq->vendor; + vndptr = (unsigned char *) breq->vendor; sprintf (vendor, "0x%02x 0x%02x 0x%02x 0x%02x", vndptr[0], vndptr[1], vndptr[2], vndptr[3]); vndptr += 4; syslog (LOG_DEBUG, "%s: vendor: %s", name, vendor); @@ -741,7 +770,7 @@ if (option == 0xFF) { sprintf (vendor, "0x%02x", option); - vndptr = breq->vendor + DHCP_VENDOR_LENGTH; + vndptr = (unsigned char *)breq->vendor + DHCP_VENDOR_LENGTH; } else if (option == 0x00) { @@ -990,7 +1019,7 @@ unsigned char * chptr; int theOption, theLength; - chptr = breq->vendor; + chptr = (unsigned char *) breq->vendor; chptr += 4; while (*chptr != 0xFF && *chptr != option) { theOption = *chptr++; @@ -1010,7 +1039,7 @@ unsigned char * chptr; unsigned int length, theOption; - chptr = bresp->vendor; + chptr = (unsigned char *) bresp->vendor; chptr += 4; while (*chptr != 0xFF && *chptr != option) { theOption = *chptr++; --- pump-0.8.24/pump.8 +++ pump-0.8.24/pump.8 @@ -1,5 +1,6 @@ .\" Copyright 1999 Red Hat Software, Inc. .\" August 2004: Updated by Thomas Hood +.\" July 2005: Updated by Roy Marples .\" .\" This man page is free documentation; you can redistribute it and/or modify .\" it under the terms of the GNU General Public License as published by @@ -29,8 +30,10 @@ .IR IFACE ] .BR "" [ \-l | \-\-lease .IR HOURS ] +.BR "" [ \-m | \-\-route\-metric +.IR METRIC ] .BR "" [ \-\-lookup\-hostname ] -.BR "" [ \-\-no\-dns "] [" \-\-no\-gateway "] [" \-\-no\-setup "] [" \-\-no\-resolvconf ] +.BR "" [ \-\-no\-dns "] [" \-\-no\-gateway "] [" \-\- no\-ntp "] [" \-\-no\-setup "] .BR "" [ \-\-release "] [" \-\-renew "] [" \-\-script = .IR ISCRIPT ] .BR "" [ \-\-status ] @@ -67,13 +70,16 @@ \-d \-\-no\-dns Don't update DNS resolver configuration \-h \-\-hostname=\fIHOSTNAME\fR Request \fIHOSTNAME\fR \-i \-\-interface=\fIIFACE\fR Manage \fIIFACE\fR rather than eth0 + \-\-keep\-up Keep the interface up when released \-k \-\-kill Kill daemon (and disable all interfaces) \-l \-\-lease=\fIHOURS\fR Request least time of \fIHOURS\fR \-\-lookup\-hostname Look up hostname in DNS \-R \-\-renew Renew lease immediately \-r \-\-release Release interface +\-m \-\-route-metric=\fIMETRIC\fR Metric to use on routes (normally 0) \-\-no\-gateway Don't configurate a default route for this interface \-\-no\-resolvconf Don't use the \fBresolvconf\fR program to update resolv.conf + \-\-no\-ntp Don't update ntp.conf \-\-no\-setup Don't set up anything \-\-script=\fISCRIPT\fR Call \fISCRIPT\fR (or null string to disable) \-s \-\-status Display interface status @@ -164,8 +170,13 @@ Use \fISEARCHPATH\fR as the DNS search path instead of the domain name returned by the server or the domain part of the fully qualified hostname. -As a machine only has a single DNS search path, this directive may -only be used globally. + +.TP +\fBkeepup\fR +Keep the interface up when released. +Normally \fBpump\fR brings the interface down when it releases its +lease, but some daemons such as ifplugd or wpa_supplicant still need the +interface to be up so that they can still work. .TP \fBnonisdomain\fR @@ -173,22 +184,24 @@ Normally \fBpump\fR sets the system's NIS domain if an NIS domain is specified by the DHCP server and the current NIS domain is empty or \fBlocaldomain\fR. -This directive may only be used within a \fBdevice\fR directive. .TP \fBnodns\fR Don't update /etc/resolv.conf when the interface is configured. -This directive may only be used within a \fBdevice\fR directive. .TP \fBnogateway\fR Ignore any default gateway suggested by the DHCP server for this device. -This can be useful on machines with multiple Ethernet cards. +This can be useful on machines with multiple devices. + +.TP +\fBnontp\fR +Don't update /etc/ntp.conf when the interface is configured. .TP \fBnosetup\fR Don't set up anything on the local machine as a result of DHCP operations. -This implies \fBnodns\fR, \fBnonisdomain\fR and \fBnogateway\fR. +This implies \fBnodns\fR, \fBnonisdomain\fR, \fBnogateway\fR and \fBnontp\fR. This option is useful, for example, if you want to perform setup in customised scripts. --- pump-0.8.24/pump.c +++ pump-0.8.24/pump.c @@ -188,9 +188,17 @@ errno = 0; - if (domain) - if(fprintf(f, "search %s\n", domain) < 0) - syslog(LOG_ERR, "failed to write resolver configuration data\n"); + fprintf(f, "# Generated by pump for interface %s\n", intf->device); + + if (domain) { + if (strchr(domain, ' ')) { + if(fprintf(f, "search %s\n", domain) < 0) + syslog(LOG_ERR, "failed to write resolver configuration data\n"); + } else { + if(fprintf(f, "search %s\n", domain) < 0) + syslog(LOG_ERR, "failed to write resolver configuration data\n"); + } + } for (i = 0; i < intf->numDns; i++) if(fprintf(f, "nameserver %s\n", inet_ntoa(intf->dnsServers[i])) < 0) @@ -301,35 +309,6 @@ free(arg); } -static void callIfupPost(struct pumpNetIntf* intf) { -#ifdef debian - /* can/should we call a debian one? */ - return; -#else - pid_t child; - char * argv[3]; - char arg[64]; - - argv[0] = "/etc/sysconfig/network-scripts/ifup-post"; - snprintf(arg,64,"ifcfg-%s",intf->device); - argv[1] = arg; - argv[2] = NULL; - - if (!(child = fork())) { - /* send the script to init */ - if (fork()) _exit(0); - - execvp(argv[0], argv); - - syslog(LOG_ERR,"failed to run %s: %s", argv[0], strerror(errno)); - - _exit(0); - } - - waitpid(child, NULL, 0); -#endif -} - static void callScript(char* script,int msg,struct pumpNetIntf* intf) { pid_t child; char * argv[20]; @@ -392,12 +371,8 @@ syslog(LOG_INFO, "configured interface %s", intf->device); - if (!(o->flags & OVERRIDE_FLAG_NOGATEWAY)) { - int i; - - for (i = intf->numGateways - 1; i >= 0; i--) - pumpSetupDefaultGateway(&intf->gateways[i]); - } + if (!(o->flags & OVERRIDE_FLAG_NOGATEWAY)) + pumpSetupDefaultGateway(intf); setupDns(intf, o); setupDomain(intf, o); @@ -509,7 +484,6 @@ } else { callScript(intf[closest].override.script, PUMP_SCRIPT_RENEWAL, &intf[closest]); - callIfupPost(&intf[closest]); } continue; /* recheck timeouts */ @@ -612,7 +586,6 @@ if (!cmd.u.result) { callScript(intf[i].override.script, PUMP_SCRIPT_RENEWAL, intf + i); - callIfupPost(intf + i); } } break; @@ -841,7 +814,6 @@ printf("\tNext server %s\n", inet_ntoa(i.nextServer)); if (i.numGateways) { - printf("\tGateway: %s\n", inet_ntoa(i.gateways[0])); printf("\tGateways:"); for (j = 0; j < i.numGateways; j++) printf(" %s", inet_ntoa(i.gateways[j])); @@ -925,12 +897,15 @@ int killDaemon = 0; int winId = 0; int release = 0, renew = 0, status = 0, lookupHostname = 0, nodns = 0; - int nogateway = 0, nobootp = 0; + int nogateway = 0, nobootp = 0, nontp = 0; int nosetup = 0; int noresolvconf = 0; + int routeMetric = 0; + int keepUp = 0; struct command cmd, response; char * configFile = "/etc/pump.conf"; char * script = NULL; + char * searchPath = NULL; struct pumpOverrideInfo * overrides; int cont; struct poptOption options[] = { @@ -942,6 +917,8 @@ { "interface", 'i', POPT_ARG_STRING, &device, 0, N_("Interface to configure (normally eth0)"), N_("iface") }, + { "keep-up", 'u', POPT_ARG_NONE, &keepUp, 0, + N_("Keep the interface up when releasing it") }, { "kill", 'k', POPT_ARG_NONE, &killDaemon, 0, N_("Kill daemon (and disable all interfaces)"), NULL }, { "lease", 'l', POPT_ARG_INT, &lease_hrs, 0, @@ -954,7 +931,9 @@ N_("Release interface"), NULL }, { "renew", 'R', POPT_ARG_NONE, &renew, 0, N_("Force immediate lease renewal"), NULL }, - { "verbose", 'v', POPT_ARG_NONE, &verbose, 0, + { "route-metric", 'm', POPT_ARG_INT, &routeMetric, 0, + N_("Metric applied to routes (normally 0)"), N_("(metric)") }, + { "verbose", 'v', POPT_ARG_NONE, &verbose, 0, N_("Log verbose debug info"), NULL }, { "status", 's', POPT_ARG_NONE, &status, 0, N_("Display interface status"), NULL }, @@ -962,12 +941,16 @@ N_("Don't update resolv.conf"), NULL }, { "no-gateway", '\0', POPT_ARG_NONE, &nogateway, 0, N_("Don't set a gateway for this interface"), NULL }, + { "no-ntp", '\0', POPT_ARG_NONE, &nontp, 0, + N_("Don't update ntp.conf"), NULL }, { "no-setup", '\0', POPT_ARG_NONE, &nosetup, 0, N_("Don't set up anything"), NULL }, { "no-resolvconf", '\0', POPT_ARG_NONE, &noresolvconf, 0, N_("Don't set up resolvconf"), NULL }, { "no-bootp", '\0', POPT_ARG_NONE, &nobootp, 0, N_("Ignore non-DHCP BOOTP responses"), NULL }, + { "search-path", 'p', POPT_ARG_STRING, &searchPath, 0, + N_("Use this DNS search path instead of the supplied one"), NULL }, { "script", '\0', POPT_ARG_STRING, &script, 0, N_("Script to use") }, { "win-client-ident", '\0', POPT_ARG_NONE, &winId, 0, @@ -1014,6 +997,11 @@ return 1; } + if (searchPath && strlen(searchPath) > sizeof(overrides->searchPath)) { + fprintf(stderr, _("%s: --search-path argument is to long\n"), PROGNAME); + return 1; + } + if (script && strlen(script) > sizeof(overrides->script)) { fprintf(stderr, _("%s: --script argument is too long\n"), PROGNAME); return 1; @@ -1033,7 +1021,7 @@ flags |= PUMP_FLAG_WINCLIENTID; if (lookupHostname) flags |= PUMP_FLAG_FORCEHNLOOKUP; - + if (killDaemon) { cmd.type = CMD_DIE; } else if (status) { @@ -1069,14 +1057,22 @@ o->flags |= OVERRIDE_FLAG_NOBOOTP; if (nogateway) o->flags |= OVERRIDE_FLAG_NOGATEWAY; + if (nontp) + o->flags |= OVERRIDE_FLAG_NONTP; if (nosetup) o->flags |= OVERRIDE_FLAG_NOSETUP | OVERRIDE_FLAG_NODNS | OVERRIDE_FLAG_NOGATEWAY | + OVERRIDE_FLAG_NONTP | OVERRIDE_FLAG_NONISDOMAIN; if (noresolvconf) o->flags |= OVERRIDE_FLAG_NORESOLVCONF; + if (keepUp) + o->flags |= OVERRIDE_FLAG_KEEPUP; + o->routeMetric = routeMetric; + if (searchPath) + strcpy(o->searchPath, searchPath); if (script) strcpy(o->script, script); --- pump-0.8.24/pump.h +++ pump-0.8.24/pump.h @@ -55,6 +55,8 @@ #define OVERRIDE_FLAG_NOBOOTP (1 << 3) #define OVERRIDE_FLAG_NOSETUP (1 << 4) #define OVERRIDE_FLAG_NORESOLVCONF (1 << 5) +#define OVERRIDE_FLAG_NONTP (1 << 6) +#define OVERRIDE_FLAG_KEEPUP (1 << 7) struct pumpOverrideInfo { char device[10]; @@ -63,6 +65,7 @@ int numRetries; int timeout; char script[1024]; + int routeMetric; }; /* all of these in_addr things are in network byte order! */ @@ -113,7 +116,7 @@ char * pumpDisableInterface(struct pumpNetIntf * intf); int pumpDhcpRenew(struct pumpNetIntf * intf); int pumpDhcpRelease(struct pumpNetIntf * intf); -int pumpSetupDefaultGateway(struct in_addr * gw); +int pumpSetupDefaultGateway(struct pumpNetIntf * intf); time_t pumpUptime(void); #define RESULT_OKAY 0