static int l2tp_ctrl_send_HELLO(l2tp_ctrl *_this) { struct l2tp_avp *avp; char buf[L2TP_AVP_MAXSIZ]; bytebuffer *bytebuf; if ((bytebuf = l2tp_ctrl_prepare_snd_buffer(_this, 1)) == NULL) { l2tp_ctrl_log(_this, LOG_ERR, "sending SCCRP failed: no buffer."); return 1; } avp = (struct l2tp_avp *)buf; /* Message Type = HELLO */ memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_MESSAGE_TYPE; avp_set_val16(avp, L2TP_AVP_MESSAGE_TYPE_HELLO); bytebuf_add_avp(bytebuf, avp, 2); if ((l2tp_ctrl_send_packet(_this, 0, bytebuf)) != 0) { l2tp_ctrl_log(_this, LOG_ERR, "sending HELLO failed"); l2tp_ctrl_stop(_this, L2TP_STOP_CCN_RCODE_GENERAL); return 1; } l2tp_ctrl_log(_this, LOG_DEBUG, "SendHELLO"); return 0; }
/* send ZLB */ static int l2tp_call_send_ZLB(l2tp_call *_this) { bytebuffer *bytebuf; l2tp_call_log(_this, LOG_INFO, "SendZLB"); bytebuf = l2tp_ctrl_prepare_snd_buffer(_this->ctrl, 1); if (bytebuf == NULL) { l2tp_call_log(_this, LOG_ERR, "sending ZLB failed: no buffer"); return 1; } return l2tp_ctrl_send_packet(_this->ctrl, _this->peer_session_id, bytebuf); }
/* * send StopCCN */ static int l2tp_ctrl_send_StopCCN(l2tp_ctrl *_this, int result) { struct l2tp_avp *avp; char buf[L2TP_AVP_MAXSIZ]; bytebuffer *bytebuf; if ((bytebuf = l2tp_ctrl_prepare_snd_buffer(_this, 1)) == NULL) { l2tp_ctrl_log(_this, LOG_ERR, "sending StopCCN failed: no buffer."); return -1; } avp = (struct l2tp_avp *)buf; /* Message Type = StopCCN */ memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_MESSAGE_TYPE; avp_set_val16(avp, L2TP_AVP_MESSAGE_TYPE_StopCCN); bytebuf_add_avp(bytebuf, avp, 2); /* Assigned Tunnel Id */ memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_ASSINGED_TUNNEL_ID; avp_set_val16(avp, _this->tunnel_id); bytebuf_add_avp(bytebuf, avp, 2); /* Result Code */ memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_RESULT_CODE; avp_set_val16(avp, result); bytebuf_add_avp(bytebuf, avp, 2); if (l2tp_ctrl_send_packet(_this, 0, bytebuf) != 0) { l2tp_ctrl_log(_this, LOG_ERR, "sending StopCCN failed"); return - 1; } l2tp_ctrl_log(_this, LOG_INFO, "SendStopCCN result=%d", result); return 0; }
/* send ICRP */ static int l2tp_call_send_ICRP(l2tp_call *_this) { int rval; struct l2tp_avp *avp; char buf[L2TP_AVP_MAXSIZ]; bytebuffer *bytebuf; bytebuf = l2tp_ctrl_prepare_snd_buffer(_this->ctrl, 1); if (bytebuf == NULL) { l2tp_call_log(_this, LOG_ERR, "sending ICRP failed: no buffer"); return 1; } avp = (struct l2tp_avp *)buf; /* Message Type = ICRP */ memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_MESSAGE_TYPE; avp_set_val16(avp, L2TP_AVP_MESSAGE_TYPE_ICRP); bytebuf_add_avp(bytebuf, avp, 2); memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_ASSIGNED_SESSION_ID; avp_set_val16(avp, _this->session_id); bytebuf_add_avp(bytebuf, avp, 2); if ((rval = l2tp_ctrl_send_packet(_this->ctrl, _this->peer_session_id, bytebuf)) != 0) { l2tp_call_log(_this, LOG_ERR, "failed to SendICRP: %m"); return 1; } l2tp_call_log(_this, LOG_INFO, "SendICRP session_id=%u", _this->session_id); return 0; }
/* called ppp output a packet */ static int l2tp_call_ppp_output(npppd_ppp *ppp, unsigned char *bytes, int nbytes, int flags) { l2tp_call *_this; bytebuffer *bytebuf; _this = ppp->phy_context; bytebuf = l2tp_ctrl_prepare_snd_buffer(_this->ctrl, _this->use_seq); if (bytebuf != NULL) { bytebuffer_put(bytebuf, bytes, nbytes); if (l2tp_call_send_data_packet(_this, bytebuf) != 0) ppp->oerrors++; else { ppp->opackets++; ppp->obytes += nbytes; } } else ppp->oerrors++; return 0; }
/* send CDN */ static int l2tp_call_send_CDN(l2tp_call *_this, int result_code, int error_code, const char *errmes, struct l2tp_avp *addavp[], int naddavp) { uint32_t val32; int i, avplen, len; struct l2tp_avp *avp; char buf[L2TP_AVP_MAXSIZ]; bytebuffer *bytebuf; L2TP_CALL_ASSERT(_this != NULL); bytebuf = l2tp_ctrl_prepare_snd_buffer(_this->ctrl, 1); if (bytebuf == NULL) { l2tp_call_log(_this, LOG_ERR, "sending CDN failed: no buffer"); return 1; } avp = (struct l2tp_avp *)buf; /* Message Type = CDN */ memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_MESSAGE_TYPE; avp_set_val16(avp, L2TP_AVP_MESSAGE_TYPE_CDN); bytebuf_add_avp(bytebuf, avp, 2); /* Result Code */ memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_RESULT_CODE; #if 0 /* * Windows 2000 work around: * Windows 2000 will return "2 - Length is wrong" in StopCCN, * when it received "length = 8 and no error code AVP". * Avoid the error, use AVP length = 10. */ if (error_code > 0) { val32 = (result_code << 16) | (error_code & 0xffff); avplen = 4; avp_set_val32(avp, val32); } else { avplen = 2; avp_set_val16(avp, result_code); } #else val32 = (result_code << 16) | (error_code & 0xffff); avplen = 4; avp_set_val32(avp, val32); #endif if (errmes != NULL) { len = MIN(strlen(errmes), L2TP_AVP_MAXSIZ - 128); memcpy(&avp->attr_value[avplen], errmes, len); avplen += len; } bytebuf_add_avp(bytebuf, avp, avplen); /* Assigned Session Id */ memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_ASSIGNED_SESSION_ID; if (_this != NULL && _this->session_id != 0) avp_set_val16(avp, _this->session_id); else avp_set_val16(avp, 0); bytebuf_add_avp(bytebuf, avp, 2); for (i = 0; i < naddavp; i++) bytebuf_add_avp(bytebuf, addavp[i], addavp[i]->length - 6); if (l2tp_ctrl_send_packet(_this->ctrl, _this->peer_session_id, bytebuf) != 0) { l2tp_call_log(_this, LOG_ERR, "Error sending CDN: %m"); return 1; } if (error_code > 0) { l2tp_call_log(_this, LOG_INFO, "SendCDN result=%s/%d error=%s/%d messsage=%s", l2tp_cdn_rcode_string(result_code), result_code, l2tp_ecode_string(error_code), error_code, (errmes == NULL)? "none" : errmes); } else { l2tp_call_log(_this, LOG_INFO, "SendCDN result=%s/%d", l2tp_cdn_rcode_string(result_code), result_code); } return 0; }
/* * send SCCRP */ static void l2tp_ctrl_send_SCCRP(l2tp_ctrl *_this) { int len; struct l2tp_avp *avp; char buf[L2TP_AVP_MAXSIZ], hbuf[HOST_NAME_MAX+1]; const char *val; bytebuffer *bytebuf; if ((bytebuf = l2tp_ctrl_prepare_snd_buffer(_this, 1)) == NULL) { l2tp_ctrl_log(_this, LOG_ERR, "sending SCCRP failed: no buffer."); return; } avp = (struct l2tp_avp *)buf; /* Message Type = SCCRP */ memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_MESSAGE_TYPE; avp_set_val16(avp, L2TP_AVP_MESSAGE_TYPE_SCCRP); bytebuf_add_avp(bytebuf, avp, 2); /* Protocol Version = 1.0 */ memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_PROTOCOL_VERSION; avp->attr_value[0] = L2TP_RFC2661_VERSION; avp->attr_value[1] = L2TP_RFC2661_REVISION; bytebuf_add_avp(bytebuf, avp, 2); /* Framing Capability = Async */ memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_FRAMING_CAPABILITIES; avp_set_val32(avp, L2TP_FRAMING_CAP_FLAGS_SYNC); bytebuf_add_avp(bytebuf, avp, 4); /* Host Name */ memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_HOST_NAME; if ((val = L2TP_CTRL_CONF(_this)->hostname) == NULL) { gethostname(hbuf, sizeof(hbuf)); val = hbuf; } len = strlen(val); memcpy(avp->attr_value, val, len); bytebuf_add_avp(bytebuf, avp, len); /* Assigned Tunnel Id */ memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_ASSINGED_TUNNEL_ID; avp_set_val16(avp, _this->tunnel_id); bytebuf_add_avp(bytebuf, avp, 2); /* Bearer Capability * This implementation never act as LAC. * memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_BEARER_CAPABILITIES; avp_set_val32(avp, 0); bytebuf_add_avp(bytebuf, avp, 4); */ /* Firmware Revision */ memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 0; avp->attr_type = L2TP_AVP_TYPE_FIRMWARE_REVISION; avp->attr_value[0] = MAJOR_VERSION; avp->attr_value[1] = MINOR_VERSION; bytebuf_add_avp(bytebuf, avp, 2); /* Vendor Name */ if ((val = L2TP_CTRL_CONF(_this)->vendor_name) != NULL) { memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 0; avp->attr_type = L2TP_AVP_TYPE_VENDOR_NAME; len = strlen(val); memcpy(avp->attr_value, val, len); bytebuf_add_avp(bytebuf, avp, len); } /* Window Size */ memset(avp, 0, sizeof(*avp)); avp->is_mandatory = 1; avp->attr_type = L2TP_AVP_TYPE_RECV_WINDOW_SIZE; avp_set_val16(avp, _this->winsz); bytebuf_add_avp(bytebuf, avp, 2); if ((l2tp_ctrl_send_packet(_this, 0, bytebuf)) != 0) { l2tp_ctrl_log(_this, LOG_ERR, "sending SCCRP failed"); l2tp_ctrl_stop(_this, L2TP_STOP_CCN_RCODE_GENERAL); return; } l2tp_ctrl_log(_this, LOG_INFO, "SendSCCRP"); }