Index: src/util.h =================================================================== --- src/util.h (revision 2480) +++ src/util.h (working copy) @@ -98,6 +98,7 @@ extern u_int32_t GenerateMagic(void); extern int GetAnyIpAddress(struct u_addr *ipaddr, const char *ifname); extern int GetEther(struct u_addr *addr, struct sockaddr_dl *hwaddr); extern int GetPeerEther(struct u_addr *addr, struct sockaddr_dl *hwaddr); +extern uint16_t GetSystemIfaceMTU(const char *ifname); extern void ppp_util_ascify(char *buf, size_t max, const char *bytes, size_t len); extern int IfaceSetFlag(const char *ifname, unsigned value); Index: src/util.c =================================================================== --- src/util.c (revision 2480) +++ src/util.c (working copy) @@ -1597,3 +1597,25 @@ ssize_t GetDataAddrs(int sock, void *dbuf, size_t dbuf return (size); } + +uint16_t GetSystemIfaceMTU(const char *ifname) +{ + struct ifreq ifr; + static int sock = -1; + + if (sock == -1 && (sock = socket(PF_INET, SOCK_DGRAM, 0)) == -1) { + Perror("[%s] %s: Socket creation error", + ifname, __FUNCTION__); + return (0); + } + + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); + + if (ioctl(sock, SIOCGIFMTU, (caddr_t)&ifr) == -1) { + Perror("[%s] %s: SIOCGIFMTU failed", ifname, __FUNCTION__); + return (0); + } + /* Let _exit() close sock */ + return (ifr.ifr_mtu); +} Index: src/pppoe.c =================================================================== --- src/pppoe.c (revision 2480) +++ src/pppoe.c (working copy) @@ -1712,6 +1712,7 @@ PppoeSetCommand(Context ctx, int ac, const char *const unsigned i; #ifdef NGM_PPPOE_SETMAXP_COOKIE int ap; + uint16_t mtu; #endif switch ((intptr_t)arg) { case SET_IFACE: @@ -1732,6 +1733,20 @@ PppoeSetCommand(Context ctx, int ac, const char *const } } strlcpy(pi->hook, hookname, sizeof(pi->hook)); + +#ifdef NGM_PPPOE_SETMAXP_COOKIE + if (pi->max_payload > 0) { + mtu = GetSystemIfaceMTU(pi->iface); + if (mtu == 0) + mtu = ETHER_MAX_LEN; + if (pi->max_payload > mtu - 8) { + pi->max_payload = mtu - 8; + Perror("[%s] PPPoE: PPP-Max-Payload" + " value reduced to %hu", + pi->iface, pi->max_payload); + } + } +#endif break; default: return(-1); @@ -1762,8 +1777,18 @@ PppoeSetCommand(Context ctx, int ac, const char *const if (ac != 1) return(-1); ap = atoi(av[0]); - if (ap < PPPOE_MRU || ap > ETHER_MAX_LEN - 8) - Error("PPP-Max-Payload value \"%s\"", av[0]); + if (pi->iface[0] == '\0') { + if (ap < PPPOE_MRU) /* postpone check for MTU */ + Error("PPP-Max-Payload value \"%s\" less than %d", + av[0], PPPOE_MRU); + } else { + mtu = GetSystemIfaceMTU(pi->iface); + if (mtu == 0) + mtu = ETHER_MAX_LEN; + if (ap < PPPOE_MRU || ap > mtu - 8) + Error("PPP-Max-Payload value \"%s\" not in a range of %d..%hu", + av[0], PPPOE_MRU, mtu); + } pi->max_payload = ap; break; #endif