diff -U 0 pump-0.8.21/config.c pump-0.8.21-r7/config.c --- pump-0.8.21/config.c 2005-07-15 17:14:04.000000000 +0100 +++ pump-0.8.21-r7/config.c 2005-07-15 14:48:32.000000000 +0100 @@ -158 +158,18 @@ - } else if (!strcmp(start, "domainsearch")) { + } else if (!strcmp(start, "routemetric")) { + poptParseArgvString(rest, &argc, &argv); + + 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, "etcdir")) { @@ -161,3 +178,11 @@ - if (overrideList != override) { - parseError(*lineNum, "domainsearch directive may not occur " - "inside of device specification"); + poptParseArgvString(rest, &argc, &argv); + + if (argc != 1) { + parseError(*lineNum, "etcdir directive expects a " + "single argument"); + return 1; + } + + len = strlen(argv[0]); + if (len >= sizeof(override->etcDir)) { + parseError(*lineNum, "etcdir directive is too long"); @@ -166,0 +192,10 @@ + /* + We don't free this as other configurations may have inherited + it. This could be the wrong decision, but leak would be tiny + so why worry? + */ + memcpy(override->etcDir, argv[0], len + 1); + free(argv); + } else if (!strcmp(start, "domainsearch")) { + size_t len; + @@ -211,0 +247,6 @@ + } else if (!strcmp(start, "nontp")) { + if (*rest) { + parseError(*lineNum, "unexpected argument to nontp directive"); + return 1; + } + override->flags |= OVERRIDE_FLAG_NONTP; @@ -222,6 +262,0 @@ - } else if (!strcmp(start, "noresolvconf")) { - if (*rest) { - parseError(*lineNum, "unexpected argument to noresolvconf directive"); - return 1; - } - override->flags |= OVERRIDE_FLAG_NORESOLVCONF; @@ -231,6 +265,0 @@ - if (overrideList != override) { - parseError(*lineNum, "script directive may not occur " - "inside of device specification"); - return 1; - } - Common subdirectories: pump-0.8.21/debian and pump-0.8.21-r7/debian diff -U 0 pump-0.8.21/dhcp.c pump-0.8.21-r7/dhcp.c --- pump-0.8.21/dhcp.c 2005-07-15 17:14:04.000000000 +0100 +++ pump-0.8.21-r7/dhcp.c 2005-07-15 14:48:32.000000000 +0100 @@ -205,0 +206 @@ + struct sockaddr_in * addrp; @@ -212,2 +212,0 @@ - - memset(&req,0,sizeof(req)); @@ -214,0 +214 @@ + memset(&req,0,sizeof(req)); @@ -215,0 +216,14 @@ + + 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; + } + @@ -285,5 +299,17 @@ - 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; + } + } @@ -291,6 +317,3 @@ - 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; @@ -310 +333 @@ -int pumpSetupDefaultGateway(struct in_addr * gw) { +int pumpSetupDefaultGateway(struct pumpNetIntf * intf) { @@ -313,0 +337 @@ + int i; @@ -316,14 +339,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; @@ -331,4 +341,23 @@ - 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; + } @@ -1435 +1464 @@ - pumpDhcpClassRun(device, flags, reqLease, reqHostname, NULL, intf, + return pumpDhcpClassRun(device, flags, reqLease, reqHostname, NULL, intf, Common subdirectories: pump-0.8.21/po and pump-0.8.21-r7/po diff -U 0 pump-0.8.21/pump.8 pump-0.8.21-r7/pump.8 --- pump-0.8.21/pump.8 2005-07-15 17:14:04.000000000 +0100 +++ pump-0.8.21-r7/pump.8 2005-07-15 14:48:32.000000000 +0100 @@ -2,0 +3 @@ +.\" July 2005: Updated by Roy Marples @@ -31,0 +33,2 @@ +.BR "" [ \-m | \-\-route\-metric +.IR METRIC ] @@ -33 +36 @@ -.BR "" [ \-\-no\-dns "] [" \-\-no\-gateway "] [" \-\-no\-setup "] [" \-\-no\-resolvconf ] +.BR "" [ \-\-no\-dns "] [" \-\-no\-gateway "] [" \-\- no\-ntp "] [" \-\-no\-setup "] @@ -67 +70,2 @@ -\-d \-\-no\-dns Don't update DNS resolver configuration +\-e \-\-etc\-dir=\fIDIR\fR Directory to create conf files (normally /etc) +\-d \-\-no\-dns Don't update resolv.conf @@ -69,0 +74 @@ + \-\-keep\-up Keep the interface up when released @@ -74,0 +80 @@ +\-m \-\-route-metric=\fIMETRIC\fR Metric to use on routes (normally 0) @@ -76 +82 @@ - \-\-no\-resolvconf Don't use the \fBresolvconf\fR program to update resolv.conf + \-\-no\-ntp Don't update ntp.conf @@ -162,0 +169,4 @@ +\fBetcdir\fR \fIETCDIRECTORY\fR +Store resolv.conf and/or ntp.conf in this directory (normally /etc). + +.TP @@ -167,2 +177,7 @@ -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. @@ -176 +190,0 @@ -This directive may only be used within a \fBdevice\fR directive. @@ -181 +194,0 @@ -This directive may only be used within a \fBdevice\fR directive. @@ -186 +199,5 @@ -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. @@ -191 +208 @@ -This implies \fBnodns\fR, \fBnonisdomain\fR and \fBnogateway\fR. +This implies \fBnodns\fR, \fBnonisdomain\fR, \fBnogateway\fR and \fBnontp\fR. @@ -196,8 +212,0 @@ -\fBnoresolvconf\fR -Don't use the resolvconf program to update /etc/resolv.conf; -instead, update /etc/resolv.conf directly. -(This option is only relevant if -.B \-\-nodns -is not used.) - -.TP @@ -207,0 +217,6 @@ +\fBroutemetric\fR \fIMETRIC\fR +Metric assigned to each route (normally 0). +Metric decide a priority when choosing where to route network traffic. +Lower metrics take a higher priority. + +.TP diff -U 0 pump-0.8.21/pump.c pump-0.8.21-r7/pump.c --- pump-0.8.21/pump.c 2005-07-15 17:14:04.000000000 +0100 +++ pump-0.8.21-r7/pump.c 2005-07-15 17:09:01.000000000 +0100 @@ -100,111 +100,2 @@ -char * readSearchPath(void) { - int fd; - struct stat sb; - char * buf; - char * start; - - fd = open("/etc/resolv.conf", O_RDONLY); - if (fd < 0) return NULL; - - fstat(fd, &sb); - buf = alloca(sb.st_size + 2); - if (read(fd, buf, sb.st_size) != sb.st_size) return NULL; - buf[sb.st_size] = '\n'; - buf[sb.st_size + 1] = '\0'; - close(fd); - - start = buf; - while (start && *start) { - while (isspace(*start) && (*start != '\n')) start++; - if (*start == '\n') { - start++; - continue; - } - - if (!strncmp("search", start, 6) && isspace(start[6])) { - start += 6; - while (isspace(*start) && *start != '\n') start++; - if (*start == '\n') return NULL; - - buf = strchr(start, '\n'); - *buf = '\0'; - return strdup(start); - } - - while (*start && (*start != '\n')) start++; - } - - return NULL; -} - -static void createResolvConf(struct pumpNetIntf * intf, struct pumpOverrideInfo * override, char * domain) { - FILE * f; - int i; - char * chptr; - int resolvconf; - - /* force a reread of /etc/resolv.conf if we need it again */ - res_close(); - endhostent(); - - if (!domain) { - domain = readSearchPath(); - if (domain) { - chptr = alloca(strlen(domain) + 1); - strcpy(chptr, domain); - free(domain); - domain = chptr; - } - } - - resolvconf = !(override->flags & OVERRIDE_FLAG_NORESOLVCONF); - if (resolvconf) { - struct stat buf; - - if (stat("/sbin/resolvconf", &buf) < 0) - resolvconf = 0; - } - - if (resolvconf) { - char *arg; - - f = NULL; - if (asprintf(&arg, "/sbin/resolvconf -a %s >/dev/null 2>&1", intf->device) >= 0) { - f = popen(arg, "w"); - free(arg); - } - if (!f) { - syslog(LOG_ERR, "error starting resolvconf: %s\n", strerror(errno)); - return; - } - } else { - f = fopen("/etc/resolv.conf", "w"); - if (!f) { - syslog(LOG_ERR, "error opening resolv.conf: %s\n", strerror(errno)); - return; - } - } - - - errno = 0; - - if (domain) - 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) - syslog(LOG_ERR, "failed to write resolver configuration data\n"); - - if (resolvconf) { - if(pclose(f) != 0) /* errno not useful on pclose failure */ - syslog(LOG_ERR, "error running resolvconf\n"); - } else { - if(fclose(f) != 0) - syslog(LOG_ERR, "error closing resolv.conf: %s\n", strerror(errno)); - } - -} - -void setupDomain(struct pumpNetIntf * intf, - struct pumpOverrideInfo * override) { +void setupDomain(struct pumpNetIntf * intf) { + struct pumpOverrideInfo *o = &intf->override; @@ -214 +105 @@ - if (override->flags & OVERRIDE_FLAG_NONISDOMAIN) + if (o->flags & OVERRIDE_FLAG_NONISDOMAIN) @@ -234 +125 @@ - if (setdomainname(intf->domain, strlen(intf->domain))) { + if (setdomainname(intf->nisDomain, strlen(intf->nisDomain))) { @@ -242,7 +133,5 @@ -void setupDns(struct pumpNetIntf * intf, struct pumpOverrideInfo * override) { - char * hn, * dn = NULL; - struct hostent * he; - - if (override->flags & OVERRIDE_FLAG_NODNS) { - return; - } +void createResolvConf(struct pumpNetIntf * intf, char * domain) { + struct pumpOverrideInfo *o = &intf->override; + FILE * f; + char resolv[1024]; + int i; @@ -250,2 +139,4 @@ - if (override->searchPath[0]) { - createResolvConf(intf, override, override->searchPath); + sprintf(resolv, "%s/resolv.conf", o->etcDir); + f = fopen(resolv, "w"); + if (!f) { + syslog(LOG_ERR, "cannot create %s: %s", resolv, strerror(errno)); @@ -254,22 +145,5 @@ - - if (intf->set & PUMP_NETINFO_HAS_DNS) { - if (!(intf->set & PUMP_NETINFO_HAS_DOMAIN)) { - if (intf->set & PUMP_NETINFO_HAS_HOSTNAME) { - hn = intf->hostname; - } else { - createResolvConf(intf, override, NULL); - - he = gethostbyaddr((char *) &intf->ip, sizeof(intf->ip), - AF_INET); - if (he) { - hn = he->h_name; - } else { - hn = NULL; - } - } - - if (hn) { - dn = strchr(hn, '.'); - if (dn) - dn++; - } + + fprintf(f, "# Generated by pump for interface %s\n", intf->device); + if (domain) { + if (strchr(domain, ' ')) { + fprintf(f, "search %s\n", domain); @@ -277 +151 @@ - dn = intf->domain; + fprintf(f, "domain %s\n", domain); @@ -278,0 +153 @@ + } @@ -280 +155,2 @@ - createResolvConf(intf, override, dn); + for (i = 0; i < intf->numDns; i++) { + fprintf(f, "nameserver %s\n", inet_ntoa(intf->dnsServers[i])); @@ -281,0 +158,2 @@ + + fclose(f); @@ -284,3 +162,4 @@ -void unsetupDns(struct pumpNetIntf * intf, struct pumpOverrideInfo * override) { - struct stat buf; - char *arg; +void setupDns(struct pumpNetIntf * intf) { + struct pumpOverrideInfo *o = &intf->override; + char * hn = NULL, * dn = NULL; + struct hostent * he; @@ -288 +167 @@ - if (override->flags & OVERRIDE_FLAG_NODNS) + if (o->flags & OVERRIDE_FLAG_NODNS) @@ -290,6 +169,2 @@ - if (override->flags & OVERRIDE_FLAG_NORESOLVCONF) - return; - if (stat("/sbin/resolvconf", &buf) < 0) - return; - if (asprintf(&arg, "/sbin/resolvconf -d %s", intf->device) < 0) { - syslog(LOG_ERR, "failed to release resolvconf: %s", strerror(errno)); + + if (!intf->set & PUMP_NETINFO_HAS_DNS) @@ -296,0 +172,22 @@ + + if (o->searchPath[0]) { + dn = o->searchPath; + } else if (intf->set & PUMP_NETINFO_HAS_DOMAIN) { + dn = intf->domain; + } else if (intf->set & PUMP_NETINFO_HAS_HOSTNAME) { + hn = intf->hostname; + } else { + createResolvConf(intf, NULL); + + he = gethostbyaddr((char *) &intf->ip, sizeof(intf->ip), AF_INET); + if (he) { + hn = he->h_name; + } else { + hn = NULL; + } + } + + if (hn) { + dn = strchr(hn, '.'); + if (dn) + dn++; @@ -299,3 +196 @@ - if (system(arg) != 0) - syslog(LOG_ERR, "resolvconf -d %s failed", intf->device); - free(arg); + createResolvConf(intf, dn); @@ -304,8 +199,5 @@ -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]; +void setupNtp(struct pumpNetIntf * intf) { + struct pumpOverrideInfo *o = &intf->override; + FILE * f; + char ntp[1024]; + int i; @@ -313,4 +205,2 @@ - argv[0] = "/etc/sysconfig/network-scripts/ifup-post"; - snprintf(arg,64,"ifcfg-%s",intf->device); - argv[1] = arg; - argv[2] = NULL; + if (o->flags & OVERRIDE_FLAG_NONTP) + return; @@ -318,3 +208,2 @@ - if (!(child = fork())) { - /* send the script to init */ - if (fork()) _exit(0); + if (! intf->set & PUMP_NETINFO_HAS_NTPSRVS) + return; @@ -322 +211,6 @@ - execvp(argv[0], argv); + sprintf(ntp, "%s/ntp.conf", o->etcDir); + f = fopen(ntp, "w"); + if (!f) { + syslog(LOG_ERR, "cannot create %s: %s\n", ntp, strerror(errno)); + return; + } @@ -324 +218,4 @@ - syslog(LOG_ERR,"failed to run %s: %s", argv[0], strerror(errno)); + fprintf(f, "# Generated by pump for interface %s\n", intf->device); + fprintf(f, "restrict default noquery notrust nomodify\n" + "restrict 127.0.0.1\n" + "driftfile /var/lib/ntp/ntp.drift\n"); @@ -326 +223,4 @@ - _exit(0); + for (i = 0; i < intf->numNtp; i++) { + fprintf(f, "restrict %s nomodify notrap noquery\n" + "server %s\n", inet_ntoa(intf->ntpServers[i]), + inet_ntoa(intf->ntpServers[i])); @@ -329,2 +229 @@ - waitpid(child, NULL, 0); -#endif + fclose(f); @@ -333 +232 @@ -static void callScript(char* script,int msg,struct pumpNetIntf* intf) { +static void callScript(struct pumpNetIntf *intf, int msg) { @@ -337,0 +237 @@ + char * script = intf->override.script; @@ -388 +287,0 @@ - @@ -397,4 +296 @@ - int i; - - for (i = intf->numGateways - 1; i >= 0; i--) - pumpSetupDefaultGateway(&intf->gateways[i]); + pumpSetupDefaultGateway(intf); @@ -403,8 +299,3 @@ - setupDns(intf, o); - setupDomain(intf, o); - - callScript(o->script, PUMP_SCRIPT_NEWLEASE, intf); -} - -static void killLease(struct pumpNetIntf *intf) { - struct pumpOverrideInfo *o = &intf->override; + setupDns(intf); + setupDomain(intf); + setupNtp(intf); @@ -412,2 +303 @@ - unsetupDns(intf, o); - callScript(o->script, PUMP_SCRIPT_DOWN, intf); + callScript(intf, PUMP_SCRIPT_NEWLEASE); @@ -502 +392 @@ - killLease(intf + closest); + callScript(intf + closest, PUMP_SCRIPT_DOWN); @@ -504 +394 @@ - killLease(intf + closest); + callScript(intf + closest, PUMP_SCRIPT_DOWN); @@ -511,3 +401 @@ - callScript(intf[closest].override.script, - PUMP_SCRIPT_RENEWAL, &intf[closest]); - callIfupPost(&intf[closest]); + callScript(&intf[closest], PUMP_SCRIPT_RENEWAL); @@ -576 +464 @@ - killLease(intf + i); + callScript(intf + i, PUMP_SCRIPT_DOWN); @@ -614,3 +502 @@ - callScript(intf[i].override.script, - PUMP_SCRIPT_RENEWAL, intf + i); - callIfupPost(intf + i); + callScript(intf + 1, PUMP_SCRIPT_RENEWAL); @@ -628 +514 @@ - killLease(intf + i); + callScript(intf + i, PUMP_SCRIPT_DOWN); @@ -844 +729,0 @@ - printf("\tGateway: %s\n", inet_ntoa(i.gateways[0])); @@ -928 +813 @@ - int nogateway = 0, nobootp = 0; + int nogateway = 0, nobootp = 0, nontp = 0; @@ -930 +815,2 @@ - int noresolvconf = 0; + int routeMetric = 0; + int keepUp = 0; @@ -933,0 +820,2 @@ + char * etcDir = "/etc"; + char * searchPath = NULL; @@ -939,0 +828,2 @@ + { "etc-dir", 'e', POPT_ARG_STRING, &etcDir, 0, + N_("Directory to store resolv.conf (normally /etc)") }, @@ -944,0 +835,2 @@ + { "keep-up", 'u', POPT_ARG_NONE, &keepUp, 0, + N_("Keep the interface up when releasing it") }, @@ -957 +849,3 @@ - { "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, @@ -964,0 +859,2 @@ + { "no-ntp", '\0', POPT_ARG_NONE, &nontp, 0, + N_("Don't update ntp.conf"), NULL }, @@ -967,2 +862,0 @@ - { "no-resolvconf", '\0', POPT_ARG_NONE, &noresolvconf, 0, - N_("Don't set up resolvconf"), NULL }, @@ -970,0 +865,2 @@ + { "search-path", 'p', POPT_ARG_STRING, &searchPath, 0, + N_("Use this DNS search path instead of the supplied one"), NULL }, @@ -1016,0 +913,10 @@ + if (etcDir && strlen(etcDir) + 12 > sizeof(overrides->etcDir)) { + fprintf(stderr, _("%s: --etc-dir argument is to long\n"), PROGNAME); + return 1; + } + + if (searchPath && strlen(searchPath) > sizeof(overrides->searchPath)) { + fprintf(stderr, _("%s: --search-path argument is to long\n"), PROGNAME); + return 1; + } + @@ -1036 +942 @@ - + @@ -1071,0 +978,2 @@ + if (nontp) + o->flags |= OVERRIDE_FLAG_NONTP; @@ -1076,0 +985 @@ + OVERRIDE_FLAG_NONTP | @@ -1078,2 +987,7 @@ - if (noresolvconf) - o->flags |= OVERRIDE_FLAG_NORESOLVCONF; + if (keepUp) + o->flags |= OVERRIDE_FLAG_KEEPUP; + o->routeMetric = routeMetric; + if (etcDir) + strcpy(o->etcDir, etcDir); + if (searchPath) + strcpy(o->searchPath, searchPath); diff -U 0 pump-0.8.21/pump.h pump-0.8.21-r7/pump.h --- pump-0.8.21/pump.h 2005-07-15 17:14:04.000000000 +0100 +++ pump-0.8.21-r7/pump.h 2005-07-15 14:48:32.000000000 +0100 @@ -57 +57,3 @@ -#define OVERRIDE_FLAG_NORESOLVCONF (1 << 5) +/* #define OVERRIDE_FLAG_NORESOLVCONF (1 << 5) */ +#define OVERRIDE_FLAG_NONTP (1 << 6) +#define OVERRIDE_FLAG_KEEPUP (1 << 7) @@ -65,0 +68,2 @@ + char etcDir[1024]; + int routeMetric; @@ -116 +120 @@ -int pumpSetupDefaultGateway(struct in_addr * gw); +int pumpSetupDefaultGateway(struct pumpNetIntf * intf);