/* 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"); }