install: chat
mkdir -p $(BINDIR) $(MANDIR)
- $(INSTALL) -s -c chat $(BINDIR)
+ $(INSTALL) -c chat $(BINDIR)
$(INSTALL) -c -m 644 chat.8 $(MANDIR)
clean:
LIBS += -lsrp -L/usr/local/ssl/lib
NEEDCRYPTOLIB = y
TARGETS += srp-entry
-EXTRAINSTALL = $(INSTALL) -s -c -m 555 srp-entry $(BINDIR)/srp-entry
+EXTRAINSTALL = $(INSTALL) -c -m 555 srp-entry $(BINDIR)/srp-entry
MANPAGES += srp-entry.8
EXTRACLEAN += srp-entry.o
NEEDDES=y
install: pppd
mkdir -p $(BINDIR) $(MANDIR)
$(EXTRAINSTALL)
- $(INSTALL) -s -c -m 555 pppd $(BINDIR)/pppd
+ $(INSTALL) -c -m 555 pppd $(BINDIR)/pppd
if chgrp pppusers $(BINDIR)/pppd 2>/dev/null; then \
chmod o-rx,u+s $(BINDIR)/pppd; fi
$(INSTALL) -c -m 444 pppd.8 $(MANDIR)
int chap_max_transmits = 10;
int chap_rechallenge_time = 0;
int chap_client_timeout_time = 60;
+int chapms_strip_domain = 0;
/*
* Command-line options.
"Set interval for rechallenge", OPT_PRIO },
{ "chap-timeout", o_int, &chap_client_timeout_time,
"Set timeout for CHAP (as client)", OPT_PRIO },
+ { "chapms-strip-domain", o_bool, &chapms_strip_domain,
+ "Strip the domain prefix before the Username", 1 },
{ NULL }
};
/* Null terminate and clean remote name. */
slprintf(rname, sizeof(rname), "%.*v", len, name);
name = rname;
+
+ /* strip the MS domain name */
+ if (chapms_strip_domain && strrchr(rname, '\\')) {
+ char tmp[MAXNAMELEN+1];
+
+ strcpy(tmp, strrchr(rname, '\\') + 1);
+ strcpy(rname, tmp);
+ }
}
if (chap_verify_hook)
#ifdef USE_EAPTLS
#include "eap-tls.h"
#endif /* USE_EAPTLS */
+#ifdef CHAPMS
+#include "magic.h"
+#include "chap_ms.h"
+#include "chap-new.h"
+#endif /* CHAPMS */
eap_state eap_states[NUM_PPP]; /* EAP state; one for each unit */
#ifdef USE_SRP
}
break;
+#ifdef CHAPMS
+ case eapMSCHAPv2Chall:
+#endif
case eapMD5Chall:
if (status != 0) {
esp->es_server.ea_state = eapBadAuth;
#endif /* USE_EAPTLS */
}
+#if CHAPMS
+static int
+eap_chapms2_verify_response(int id, char *name,
+ unsigned char *secret, int secret_len,
+ unsigned char *challenge, unsigned char *response,
+ char *message, int message_space)
+{
+ unsigned char md[MS_CHAP2_RESPONSE_LEN];
+ char saresponse[MS_AUTH_RESPONSE_LENGTH+1];
+ int challenge_len, response_len;
+
+ challenge_len = *challenge++; /* skip length, is 16 */
+ response_len = *response++;
+ if (response_len != MS_CHAP2_RESPONSE_LEN)
+ goto bad; /* not even the right length */
+
+ /* Generate the expected response and our mutual auth. */
+ ChapMS2(challenge, &response[MS_CHAP2_PEER_CHALLENGE], name,
+ (char *)secret, secret_len, md,
+ (unsigned char *)saresponse, MS_CHAP2_AUTHENTICATOR);
+
+ /* compare MDs and send the appropriate status */
+ /*
+ * Per RFC 2759, success message must be formatted as
+ * "S=<auth_string> M=<message>"
+ * where
+ * <auth_string> is the Authenticator Response (mutual auth)
+ * <message> is a text message
+ *
+ * However, some versions of Windows (win98 tested) do not know
+ * about the M=<message> part (required per RFC 2759) and flag
+ * it as an error (reported incorrectly as an encryption error
+ * to the user). Since the RFC requires it, and it can be
+ * useful information, we supply it if the peer is a conforming
+ * system. Luckily (?), win98 sets the Flags field to 0x04
+ * (contrary to RFC requirements) so we can use that to
+ * distinguish between conforming and non-conforming systems.
+ *
+ * Special thanks to Alex Swiridov <say@real.kharkov.ua> for
+ * help debugging this.
+ */
+ if (memcmp(&md[MS_CHAP2_NTRESP], &response[MS_CHAP2_NTRESP],
+ MS_CHAP2_NTRESP_LEN) == 0) {
+ if (response[MS_CHAP2_FLAGS])
+ slprintf(message, message_space, "S=%s", saresponse);
+ else
+ slprintf(message, message_space, "S=%s M=%s",
+ saresponse, "Access granted");
+ return 1;
+ }
+
+ bad:
+ /*
+ * Failure message must be formatted as
+ * "E=e R=r C=c V=v M=m"
+ * where
+ * e = error code (we use 691, ERROR_AUTHENTICATION_FAILURE)
+ * r = retry (we use 1, ok to retry)
+ * c = challenge to use for next response, we reuse previous
+ * v = Change Password version supported, we use 0
+ * m = text message
+ *
+ * The M=m part is only for MS-CHAPv2. Neither win2k nor
+ * win98 (others untested) display the message to the user anyway.
+ * They also both ignore the E=e code.
+ *
+ * Note that it's safe to reuse the same challenge as we don't
+ * actually accept another response based on the error message
+ * (and no clients try to resend a response anyway).
+ *
+ * Basically, this whole bit is useless code, even the small
+ * implementation here is only because of overspecification.
+ */
+ slprintf(message, message_space, "E=691 R=1 C=%0.*B V=0 M=%s",
+ challenge_len, challenge, "Access denied");
+ return 0;
+}
+
+static struct chap_digest_type eap_chapms2_digest = {
+ CHAP_MICROSOFT_V2, /* code */
+ NULL, /* chapms2_generate_challenge, */
+ eap_chapms2_verify_response,
+ NULL, /* chapms2_make_response, */
+ NULL, /* chapms2_check_success, */
+ NULL, /* chapms_handle_failure, */
+};
+
+/*
+ * eap_chap_verify_response - check whether the peer's response matches
+ * what we think it should be. Returns 1 if it does (authentication
+ * succeeded), or 0 if it doesn't.
+ */
+static int
+eap_chap_verify_response(char *name, char *ourname, int id,
+ struct chap_digest_type *digest,
+ unsigned char *challenge, unsigned char *response,
+ char *message, int message_space)
+{
+ int ok;
+ unsigned char secret[MAXSECRETLEN];
+ int secret_len;
+
+ /* Get the secret that the peer is supposed to know */
+ if (!get_secret(0, name, ourname, (char *)secret, &secret_len, 1)) {
+ error("No CHAP secret found for authenticating %q", name);
+ return 0;
+ }
+
+ ok = digest->verify_response(id, name, secret, secret_len, challenge,
+ response, message, message_space);
+ memset(secret, 0, sizeof(secret));
+
+ return ok;
+}
+
+/*
+ * Format and send an CHAPV2-Success/Failure EAP Request message.
+ */
+static void
+eap_chapms2_send_request(eap_state *esp, u_char id,
+ u_char opcode, u_char chapid,
+ char *message, int message_len)
+{
+ u_char *outp;
+ int msglen;
+
+ outp = outpacket_buf;
+
+ MAKEHEADER(outp, PPP_EAP);
+
+ msglen = EAP_HEADERLEN + 5 * sizeof (u_char);
+ msglen += message_len;
+
+ PUTCHAR(EAP_REQUEST, outp);
+ PUTCHAR(id, outp);
+ PUTSHORT(msglen, outp);
+ PUTCHAR(EAPT_MSCHAPV2, outp);
+ PUTCHAR(opcode, outp);
+ PUTCHAR(chapid, outp);
+ /* MS len */
+ PUTSHORT(msglen - 5, outp);
+ BCOPY(message, outp, message_len);
+
+ output(esp->es_unit, outpacket_buf, PPP_HDRLEN + msglen);
+
+ if (opcode == CHAP_SUCCESS) {
+ auth_peer_success(esp->es_unit, PPP_EAP, 0,
+ esp->es_server.ea_peer, esp->es_server.ea_peerlen);
+ }
+ else {
+ esp->es_server.ea_state = eapBadAuth;
+ auth_peer_fail(esp->es_unit, PPP_EAP);
+ }
+}
+#endif /* CHAPMS */
+
/*
* Format an EAP Request message and send it to the peer. Message
* type depends on current state. (Server operation)
INCPTR(esp->es_server.ea_namelen, outp);
break;
+#ifdef CHAPMS
+ case eapMSCHAPv2Chall:
+ challen = 0x10;
+ esp->es_challen = challen;
+ esp->es_challenge[0] = challen;
+ random_bytes(&esp->es_challenge[1], challen);
+
+ PUTCHAR(EAPT_MSCHAPV2, outp);
+ PUTCHAR(CHAP_CHALLENGE, outp);
+ PUTCHAR(esp->es_server.ea_id, outp);
+ /* MS len */
+ PUTSHORT(5 + challen +
+ esp->es_server.ea_namelen,
+ outp);
+ /* challen + challenge */
+ BCOPY(esp->es_challenge, outp, challen+1);
+ INCPTR(challen+1, outp);
+ BCOPY(esp->es_server.ea_name,
+ outp,
+ esp->es_server.ea_namelen);
+ INCPTR(esp->es_server.ea_namelen, outp);
+ break;
+#endif /* CHAPMS */
+
#ifdef USE_EAPTLS
case eapTlsStart:
PUTCHAR(EAPT_TLS, outp);
struct eaptls_session *ets;
u_char flags;
#endif /* USE_EAPTLS */
+#ifdef CHAPMS
+ u_char opcode;
+ int (*chap_verifier)(char *, char *, int, struct chap_digest_type *,
+ unsigned char *, unsigned char *, char *, int);
+ char response_message[256];
+#endif /* CHAPMS */
/*
* Ignore responses if we're not open
break;
#endif /* USE_EAPTLS */
+#ifdef CHAPMS
+ case EAPT_MSCHAPV2:
+ info("EAP: peer proposes MSCHAPv2");
+ esp->es_server.ea_state = eapMSCHAPv2Chall;
+ break;
+#endif /* CHAPMS */
+
default:
dbglog("EAP: peer requesting unknown Type %d", vallen);
switch (esp->es_server.ea_state) {
TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
break;
+#ifdef CHAPMS
+ case EAPT_MSCHAPV2:
+ if (len < 1) {
+ error("EAP: received MSCHAPv2 with no data");
+ eap_figure_next_state(esp, 1);
+ break;
+ }
+ GETCHAR(opcode, inp);
+ len--;
+
+ switch (opcode) {
+ case CHAP_RESPONSE:
+ if (esp->es_server.ea_state != eapMSCHAPv2Chall) {
+ error("EAP: unexpected MSCHAPv2-Response");
+ eap_figure_next_state(esp, 1);
+ break;
+ }
+ /* skip MS ID + len */
+ INCPTR(3, inp);
+ GETCHAR(vallen, inp);
+ len -= 4;
+
+ if (vallen != MS_CHAP2_RESPONSE_LEN || vallen > len) {
+ error("EAP: Invalid MSCHAPv2-Response "
+ "length %d", vallen);
+ eap_figure_next_state(esp, 1);
+ break;
+ }
+
+ /* Not so likely to happen. */
+ if (len - vallen >= sizeof (rhostname)) {
+ dbglog("EAP: trimming really long peer name down");
+ BCOPY(inp + vallen, rhostname, sizeof (rhostname) - 1);
+ rhostname[sizeof (rhostname) - 1] = '\0';
+ } else {
+ BCOPY(inp + vallen, rhostname, len - vallen);
+ rhostname[len - vallen] = '\0';
+ }
+
+ /* In case the remote doesn't give us his name. */
+ if (explicit_remote ||
+ (remote_name[0] != '\0' && vallen == len))
+ strlcpy(rhostname, remote_name, sizeof (rhostname));
+
+ if (chap_verify_hook)
+ chap_verifier = chap_verify_hook;
+ else
+ chap_verifier = eap_chap_verify_response;
+
+ esp->es_server.ea_id += 1;
+ if ((*chap_verifier)(rhostname,
+ esp->es_server.ea_name,
+ id,
+ &eap_chapms2_digest,
+ esp->es_challenge,
+ inp - 1,
+ response_message,
+ sizeof(response_message)))
+ {
+ info("EAP: MSCHAPv2 success for peer %q",
+ rhostname);
+ esp->es_server.ea_type = EAPT_MSCHAPV2;
+ eap_chapms2_send_request(esp,
+ esp->es_server.ea_id,
+ CHAP_SUCCESS,
+ esp->es_server.ea_id,
+ response_message,
+ strlen(response_message));
+ eap_figure_next_state(esp, 0);
+ if (esp->es_rechallenge != 0)
+ TIMEOUT(eap_rechallenge, esp, esp->es_rechallenge);
+ }
+ else {
+ warn("EAP: MSCHAPv2 failure for peer %q",
+ rhostname);
+ eap_chapms2_send_request(esp,
+ esp->es_server.ea_id,
+ CHAP_FAILURE,
+ esp->es_server.ea_id,
+ response_message,
+ strlen(response_message));
+ }
+ break;
+ case CHAP_SUCCESS:
+ info("EAP: MSCHAPv2 success confirmed");
+ break;
+ case CHAP_FAILURE:
+ info("EAP: MSCHAPv2 failure confirmed");
+ break;
+ default:
+ error("EAP: Unhandled MSCHAPv2 opcode %d", opcode);
+ eap_send_nak(esp, id, EAPT_SRP);
+ }
+
+ break;
+#endif /* CHAPMS */
+
#ifdef USE_SRP
case EAPT_SRP:
if (len < 1) {
"OTP", "Generic-Token", NULL, NULL,
"RSA", "DSS", "KEA", "KEA-Validate",
"TLS", "Defender", "Windows 2000", "Arcot",
- "Cisco", "Nokia", "SRP"
+ "Cisco", "Nokia", "SRP", NULL,
+ "TTLS", "RAS", "AKA", "3COM", "PEAP",
+ "MSCHAPv2"
};
static int
#ifdef USE_EAPTLS
u_char flags;
#endif /* USE_EAPTLS */
+#ifdef CHAPMS
+ u_char opcode;
+#endif /* CHAPMS */
if (inlen < EAP_HEADERLEN)
return (0);
}
break;
+#ifdef CHAPMS
+ case EAPT_MSCHAPV2:
+ if (len <= 0)
+ break;
+ GETCHAR(opcode, inp);
+ len--;
+ switch (opcode) {
+ case CHAP_CHALLENGE:
+ INCPTR(3, inp);
+ len -= 3;
+ GETCHAR(vallen, inp);
+ len--;
+ if (vallen > len)
+ goto truncated;
+ len -= vallen;
+ printer(arg, " Challenge <");
+ for (; vallen > 0; --vallen) {
+ u_char val;
+ GETCHAR(val, inp);
+ printer(arg, "%.2x", val);
+ }
+ printer(arg, ">");
+ if (len > 0) {
+ printer(arg, ", <Name ");
+ print_string((char *)inp, len, printer, arg);
+ printer(arg, ">");
+ INCPTR(len, inp);
+ len = 0;
+ } else {
+ printer(arg, ", <No name>");
+ }
+ break;
+ case CHAP_SUCCESS:
+ INCPTR(3, inp);
+ len -= 3;
+ printer(arg, " Success <Message ");
+ print_string((char *)inp, len, printer, arg);
+ printer(arg, ">");
+ break;
+ case CHAP_FAILURE:
+ INCPTR(3, inp);
+ len -= 3;
+ printer(arg, " Failure <Message ");
+ print_string((char *)inp, len, printer, arg);
+ printer(arg, ">");
+ break;
+ default:
+ INCPTR(3, inp);
+ len -= 3;
+ printer(arg, " opcode=0x%x <%.*B>", opcode, len, inp);
+ break;
+ }
+ break;
+#endif /* CHAPMS */
+
#ifdef USE_EAPTLS
case EAPT_TLS:
if (len < 1)
}
break;
+#ifdef CHAPMS
+ case EAPT_MSCHAPV2:
+ if (len <= 0)
+ break;
+ GETCHAR(opcode, inp);
+ len--;
+ switch (opcode) {
+ case CHAP_RESPONSE:
+ INCPTR(3, inp);
+ len -= 3;
+ GETCHAR(vallen, inp);
+ len--;
+ if (vallen > len)
+ goto truncated;
+ len -= vallen;
+ printer(arg, " Response <");
+ for (; vallen > 0; --vallen) {
+ u_char val;
+ GETCHAR(val, inp);
+ printer(arg, "%.2x", val);
+ }
+ printer(arg, ">");
+ if (len > 0) {
+ printer(arg, ", <Name ");
+ print_string((char *)inp, len, printer, arg);
+ printer(arg, ">");
+ INCPTR(len, inp);
+ len = 0;
+ } else {
+ printer(arg, ", <No name>");
+ }
+ break;
+ case CHAP_SUCCESS:
+ printer(arg, " Success");
+ break;
+ case CHAP_FAILURE:
+ printer(arg, " Failure");
+ break;
+ default:
+ printer(arg, " opcode=0x%x <%.*B>", opcode, len, inp);
+ break;
+ }
+ break;
+#endif /* CHAPMS */
+
case EAPT_SRP:
if (len < 1)
goto truncated;
#define EAPT_NOKIACARD 18 /* Nokia IP smart card */
#define EAPT_SRP 19 /* Secure Remote Password */
/* 20 is deprecated */
+#define EAPT_TTLS 21 /* EAP Tunneled TLS Authentication Protocol RFC5281 */
+#define EAPT_RAS 22 /* Remote Access Service */
+#define EAPT_AKA 23 /* EAP method for 3rd Generation Authentication and Key Agreement RFC4187 */
+#define EAPT_3COM 24 /* EAP-3Com Wireless */
+#define EAPT_PEAP 25 /* Protected EAP */
+#define EAPT_MSCHAPV2 26 /* EAP-MSCHAPv2 RFC-draft-kamath-pppext-eap-mschapv2-02 */
+
+/* OpCodes for MSCHAPv2 */
+#define CHAP_CHALLENGE 1
+#define CHAP_RESPONSE 2
+#define CHAP_SUCCESS 3
+#define CHAP_FAILURE 4
/* EAP SRP-SHA1 Subtypes */
#define EAPSRP_CHALLENGE 1 /* Request 1 - Challenge */
eapSRP2, /* Sent EAP SRP-SHA1 Subtype 2 */
eapSRP3, /* Sent EAP SRP-SHA1 Subtype 3 */
eapMD5Chall, /* Sent MD5-Challenge */
+ eapMSCHAPv2Chall, /* Sent MSCHAPv2-Challenge */
eapOpen, /* Completed authentication */
eapSRP4, /* Sent EAP SRP-SHA1 Subtype 4 */
eapBadAuth /* Failed authentication */
"Initial", "Pending", "Closed", "Listen", "Identify", \
"TlsStart", "TlsRecv", "TlsSendAck", "TlsSend", "TlsRecvAck", "TlsRecvClient",\
"TlsSendAlert", "TlsRecvAlertAck" , "TlsRecvSuccess", "TlsRecvFailure", \
- "SRP1", "SRP2", "SRP3", "MD5Chall", "Open", "SRP4", "BadAuth"
+ "SRP1", "SRP2", "SRP3", "MD5Chall", "MSCHAPv2Chall", "Open", "SRP4", "BadAuth"
#ifdef USE_EAPTLS
#define eap_client_active(esp) ((esp)->es_client.ea_state != eapInitial &&\
*/
if (ipcp_script_state == s_down && ipcp_script_pid == 0) {
ipcp_script_state = s_up;
- ipcp_script(_PATH_IPUP, 0);
+ ipcp_script(path_ipup, 0);
}
}
/* Execute the ip-down script */
if (ipcp_script_state == s_up && ipcp_script_pid == 0) {
ipcp_script_state = s_down;
- ipcp_script(_PATH_IPDOWN, 0);
+ ipcp_script(path_ipdown, 0);
}
}
case s_up:
if (ipcp_fsm[0].state != OPENED) {
ipcp_script_state = s_down;
- ipcp_script(_PATH_IPDOWN, 0);
+ ipcp_script(path_ipdown, 0);
}
break;
case s_down:
if (ipcp_fsm[0].state == OPENED) {
ipcp_script_state = s_up;
- ipcp_script(_PATH_IPUP, 0);
+ ipcp_script(path_ipup, 0);
}
break;
}
struct protent *protp;
char numbuf[16];
+ strlcpy(path_ipup, _PATH_IPUP, sizeof(path_ipup));
+ strlcpy(path_ipdown, _PATH_IPDOWN, sizeof(path_ipdown));
+
link_stats_valid = 0;
new_phase(PHASE_INITIALIZE);
/* update pid files if they have been written already */
if (pidfilename[0])
create_pidfile(pid);
- if (linkpidfile[0])
- create_linkpidfile(pid);
+ create_linkpidfile(pid);
exit(0); /* parent dies */
}
setsid();
bool tune_kernel; /* may alter kernel settings */
int connect_delay = 1000; /* wait this many ms after connect script */
int req_unit = -1; /* requested interface unit */
+char path_ipup[MAXPATHLEN]; /* pathname of ip-up script */
+char path_ipdown[MAXPATHLEN];/* pathname of ip-down script */
char req_ifname[MAXIFNAMELEN]; /* requested interface name */
bool multilink = 0; /* Enable multilink operation */
char *bundle_name = NULL; /* bundle name for multilink */
"Metric to use for the default route (Linux only; -1 for default behavior)",
OPT_PRIV|OPT_LLIMIT|OPT_INITONLY, NULL, 0, -1 },
+ { "ip-up-script", o_string, path_ipup,
+ "Set pathname of ip-up script",
+ OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN },
+ { "ip-down-script", o_string, path_ipdown,
+ "Set pathname of ip-down script",
+ OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN },
+
#ifdef HAVE_MULTILINK
{ "multilink", o_bool, &multilink,
"Enable multilink operation", OPT_PRIO | 1 },
{
struct sockaddr_atmpvc addr;
extern struct stat devstat;
+
if (device_got_set)
return 0;
- //info("PPPoATM setdevname_pppoatm: '%s'", cp);
+
memset(&addr, 0, sizeof addr);
if (text2atm(cp, (struct sockaddr *) &addr, sizeof(addr),
T2A_PVC | T2A_NAME | T2A_WILDCARD) < 0) {
- if(doit)
- info("atm does not recognize: %s", cp);
+ if (doit)
+ info("cannot parse the ATM address: %s", cp);
return 0;
- }
- if (!doit) return 1;
- //if (!dev_set_ok()) return -1;
+ }
+ if (!doit)
+ return 1;
+
memcpy(&pvcaddr, &addr, sizeof pvcaddr);
strlcpy(devnam, cp, sizeof devnam);
devstat.st_mode = S_IFSOCK;
lcp_allowoptions[0].neg_asyncmap = 0;
lcp_wantoptions[0].neg_pcompression = 0;
}
- info("PPPoATM setdevname_pppoatm - SUCCESS:%s", cp);
device_got_set = 1;
return 1;
}
static void set_line_discipline_pppoatm(int fd)
{
struct atm_backend_ppp be;
+
be.backend_num = ATM_BACKEND_PPP;
if (!llc_encaps)
be.encaps = PPPOATM_ENCAPS_VC;
be.encaps = PPPOATM_ENCAPS_LLC;
else
be.encaps = PPPOATM_ENCAPS_AUTODETECT;
+
if (ioctl(fd, ATM_SETBACKEND, &be) < 0)
fatal("ioctl(ATM_SETBACKEND): %m");
}
void plugin_init(void)
{
-#if defined(__linux__)
+#ifdef linux
extern int new_style_driver; /* From sys-linux.c */
if (!ppp_available() && !new_style_driver)
fatal("Kernel doesn't support ppp_generic - "
#else
fatal("No PPPoATM support on this OS");
#endif
- info("PPPoATM plugin_init");
add_options(pppoa_options);
}
+
struct channel pppoa_channel = {
options: pppoa_options,
process_extra_options: NULL,
install: all
$(INSTALL) -d -m 755 $(LIBDIR)
- $(INSTALL) -s -c -m 755 radius.so $(LIBDIR)
- $(INSTALL) -s -c -m 755 radattr.so $(LIBDIR)
- $(INSTALL) -s -c -m 755 radrealms.so $(LIBDIR)
+ $(INSTALL) -c -m 755 radius.so $(LIBDIR)
+ $(INSTALL) -c -m 755 radattr.so $(LIBDIR)
+ $(INSTALL) -c -m 755 radrealms.so $(LIBDIR)
$(INSTALL) -c -m 444 pppd-radius.8 $(MANDIR)
$(INSTALL) -c -m 444 pppd-radattr.8 $(MANDIR)
{
case PW_TYPE_STRING:
+ case PW_TYPE_IFID:
+ case PW_TYPE_IPV6ADDR:
+ case PW_TYPE_IPV6PREFIX:
memcpy (pair->strvalue, (char *) ptr, (size_t) attrlen);
pair->strvalue[attrlen] = '\0';
pair->lvalue = attrlen;
int rc_avpair_tostr (VALUE_PAIR *pair, char *name, int ln, char *value, int lv)
{
DICT_VALUE *dval;
- char buffer[32];
+ char buffer[INET6_ADDRSTRLEN + 4]; // for a prefix: addr + '/' + prefixlen
struct in_addr inad;
unsigned char *ptr;
+ char *str;
*name = *value = '\0';
strncpy(value, buffer, lv-1);
break;
+ case PW_TYPE_IFID:
+ ptr = pair->strvalue;
+ snprintf(buffer, sizeof (buffer), "%x:%x:%x:%x",
+ (ptr[0] << 8) + ptr[1], (ptr[2] << 8) + ptr[3],
+ (ptr[4] << 8) + ptr[5], (ptr[6] << 8) + ptr[7]);
+ strncpy(value, buffer, lv-1);
+ break;
+
+ case PW_TYPE_IPV6ADDR:
+ inet_ntop(AF_INET6, pair->strvalue, buffer, sizeof (buffer));
+ strncpy(value, buffer, lv-1);
+ break;
+
+ case PW_TYPE_IPV6PREFIX:
+ inet_ntop(AF_INET6, pair->strvalue + 2, buffer, sizeof (buffer));
+ str = buffer + strlen(buffer);
+ snprintf(str, sizeof (buffer) - (str - buffer), "/%d", *(pair->strvalue + 1));
+ strncpy(value, buffer, lv-1);
+ break;
+
default:
error("rc_avpair_tostr: unknown attribute type %d", pair->type);
return (-1);
{
type = PW_TYPE_DATE;
}
+ else if (strcmp (typestr, "ifid") == 0)
+ {
+ type = PW_TYPE_IFID;
+ }
+ else if (strcmp (typestr, "ipv6addr") == 0)
+ {
+ type = PW_TYPE_IPV6ADDR;
+ }
+ else if (strcmp (typestr, "ipv6prefix") == 0)
+ {
+ type = PW_TYPE_IPV6PREFIX;
+ }
else
{
error("rc_read_dictionary: invalid type on line %d of dictionary %s",
#define PW_TYPE_INTEGER 1
#define PW_TYPE_IPADDR 2
#define PW_TYPE_DATE 3
+#define PW_TYPE_ABINARY 4
+#define PW_TYPE_OCTETS 5
+#define PW_TYPE_IFID 6
+#define PW_TYPE_IPV6ADDR 7
+#define PW_TYPE_IPV6PREFIX 8
+#define PW_TYPE_BYTE 9
+#define PW_TYPE_SHORT 10
+#define PW_TYPE_ETHERNET 11
+#define PW_TYPE_SIGNED 12
+#define PW_TYPE_COMBO_IP 13
+#define PW_TYPE_TLV 14
/* standard RADIUS codes */
install: all
$(INSTALL) -d -m 755 $(LIBDIR)
- $(INSTALL) -s -c -m 4550 rp-pppoe.so $(LIBDIR)
+ $(INSTALL) -c -m 4550 rp-pppoe.so $(LIBDIR)
$(INSTALL) -d -m 755 $(BINDIR)
- $(INSTALL) -s -c -m 555 pppoe-discovery $(BINDIR)
+ $(INSTALL) -c -m 555 pppoe-discovery $(BINDIR)
clean:
rm -f *.o *.so pppoe-discovery
extern int connect_delay; /* Time to delay after connect script */
extern int max_data_rate; /* max bytes/sec through charshunt */
extern int req_unit; /* interface unit number to use */
+extern char path_ipup[MAXPATHLEN]; /* pathname of ip-up script */
+extern char path_ipdown[MAXPATHLEN]; /* pathname of ip-down script */
extern char req_ifname[MAXIFNAMELEN]; /* interface name to use */
extern bool multilink; /* enable multilink operation */
extern bool noendpoint; /* don't send or accept endpt. discrim. */
if (new_style_driver) {
int flags;
+ /* If a ppp_fd is already open, close it first */
+ if (ppp_fd >= 0) {
+ close(ppp_fd);
+ remove_fd(ppp_fd);
+ ppp_fd = -1;
+ }
+
/* Open an instance of /dev/ppp and connect the channel to it */
if (ioctl(fd, PPPIOCGCHAN, &chindex) == -1) {
error("Couldn't get channel number: %m");
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd < 0)
- return 0;
+ return -1;
memset(&ifreq.ifr_hwaddr, 0, sizeof(struct sockaddr));
strlcpy(ifreq.ifr_name, name, sizeof(ifreq.ifr_name));
ret = ioctl(sock_fd, SIOCGIFHWADDR, &ifreq);
* get_first_ethernet - return the name of the first ethernet-style
* interface on this system.
*/
+static char first_ether_name[IF_NAMESIZE];
char *
get_first_ethernet(void)
{
- return "eth0";
+ struct if_nameindex *if_ni, *i;
+ struct ifreq ifreq;
+ int ret, sock_fd;
+
+ sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock_fd < 0)
+ return NULL;
+
+ if_ni = if_nameindex();
+ if (!if_ni) {
+ close(sock_fd);
+ return NULL;
+ }
+
+ first_ether_name[0] = 0;
+
+ for (i = if_ni; !(i->if_index == 0 && i->if_name == NULL); i++) {
+ memset(&ifreq.ifr_hwaddr, 0, sizeof(struct sockaddr));
+ strlcpy(ifreq.ifr_name, i->if_name, sizeof(ifreq.ifr_name));
+ ret = ioctl(sock_fd, SIOCGIFHWADDR, &ifreq);
+ if (ret >= 0 && ifreq.ifr_hwaddr.sa_family == ARPHRD_ETHER) {
+ strlcpy(first_ether_name, i->if_name, sizeof(first_ether_name));
+ break;
+ }
+ }
+
+ if_freenameindex(if_ni);
+ close(sock_fd);
+
+ if (!first_ether_name[0])
+ return NULL;
+
+ return first_ether_name;
}
/********************************************************************
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
- ifr.ifr_metric = link_mtu;
+ ifr.ifr_metric = mtu;
if (ioctl(ipfd, SIOCSIFMTU, &ifr) < 0) {
error("Couldn't set IP MTU (%s): %m", ifr.ifr_name);
}
memset(&lifr, 0, sizeof(lifr));
strlcpy(lifr.lifr_name, ifname, sizeof(lifr.lifr_name));
- lifr.lifr_mtu = link_mtu;
+ lifr.lifr_mtu = mtu;
if (ioctl(fd, SIOCSLIFMTU, &lifr) < 0) {
close(fd);
error("Couldn't set IPv6 MTU (%s): %m", ifr.ifr_name);
BINDIR = $(DESTDIR)/sbin
MANDIR = $(DESTDIR)/share/man/man8
+DO_DEFLATE=y
+DO_BSD_COMPRESS=y
+HAVE_ZLIB=n
+
CFLAGS= -O -I../include/net
-OBJS = pppdump.o bsd-comp.o deflate.o zlib.o
+OBJS = pppdump.o
+LIBS =
+
+ifdef DO_DEFLATE
+CFLAGS += -DDO_DEFLATE=1
+OBJS += deflate.o
+ifdef HAVE_ZLIB
+LIBS += -lz
+else
+OBJS += zlib.o
+endif
+else
+CFLAGS += -DDO_DEFLATE=0
+endif
+
+ifdef DO_BSD_COMPRESS
+CFLAGS += -DDO_BSD_COMPRESS=1
+OBJS += bsd-comp.o
+else
+CFLAGS += -DDO_BSD_COMPRESS=0
+endif
INSTALL= install
all: pppdump
pppdump: $(OBJS)
- $(CC) $(LDFLAGS) -o pppdump $(OBJS)
+ $(CC) $(LDFLAGS) -o pppdump $(OBJS) $(LIBS)
clean:
rm -f pppdump $(OBJS) *~
install:
mkdir -p $(BINDIR) $(MANDIR)
- $(INSTALL) -s -c pppdump $(BINDIR)
+ $(INSTALL) -c pppdump $(BINDIR)
$(INSTALL) -c -m 444 pppdump.8 $(MANDIR)
install: pppstats
-mkdir -p $(MANDIR)
- $(INSTALL) -s -c pppstats $(BINDIR)
+ $(INSTALL) -c pppstats $(BINDIR)
$(INSTALL) -c -m 444 pppstats.8 $(MANDIR)
pppstats: $(PPPSTATSRCS)