CFG_RW *NewCfgRwEx2W(FOLDER **root, wchar_t *cfg_name, bool dont_backup, wchar_t *template_name) { CFG_RW *rw; FOLDER *f; bool loaded_from_template = false; // Validate arguments if (cfg_name == NULL || root == NULL) { return NULL; } f = CfgReadW(cfg_name); if (f == NULL) { // Load from template if (UniIsEmptyStr(template_name) == false) { f = CfgReadW(template_name); if (f != NULL) { loaded_from_template = true; goto LABEL_CONTIUNE; } } rw = ZeroMalloc(sizeof(CFG_RW)); rw->lock = NewLock(); rw->FileNameW = CopyUniStr(cfg_name); rw->FileName = CopyUniToStr(cfg_name); rw->Io = FileCreateW(cfg_name); *root = NULL; rw->DontBackup = dont_backup; return rw; } LABEL_CONTIUNE: rw = ZeroMalloc(sizeof(CFG_RW)); rw->FileNameW = CopyUniStr(cfg_name); rw->FileName = CopyUniToStr(cfg_name); if (loaded_from_template == false) { rw->Io = FileOpenW(cfg_name, false); } else { rw->Io = FileCreateW(cfg_name); } rw->lock = NewLock(); *root = f; rw->DontBackup = dont_backup; return rw; }
// Convert the token information to the SEC_INFO SEC_INFO *TokenInfoToSecInfo(void *p_t) { SEC_INFO *s; char buf[MAX_SIZE]; CK_TOKEN_INFO *t = (CK_TOKEN_INFO *)p_t; // Validate arguments if (t == NULL) { return NULL; } s = ZeroMalloc(sizeof(SEC_INFO)); // Label Zero(buf, sizeof(buf)); Copy(buf, t->label, sizeof(t->label)); s->Label = ZeroMalloc(CalcUtf8ToUni(buf, 0)); Utf8ToUni(s->Label, 0, buf, 0); // ManufacturerId Zero(buf, sizeof(buf)); Copy(buf, t->manufacturerID, sizeof(t->manufacturerID)); s->ManufacturerId = ZeroMalloc(CalcUtf8ToUni(buf, 0)); Utf8ToUni(s->ManufacturerId, 0, buf, 0); // Model Zero(buf, sizeof(buf)); Copy(buf, t->model, sizeof(t->model)); s->Model = ZeroMalloc(CalcUtf8ToUni(buf, 0)); Utf8ToUni(s->Model, 0, buf, 0); // SerialNumber Zero(buf, sizeof(buf)); Copy(buf, t->serialNumber, sizeof(t->serialNumber)); s->SerialNumber = ZeroMalloc(CalcUtf8ToUni(buf, 0)); Utf8ToUni(s->SerialNumber, 0, buf, 0); // Numeric value s->MaxSession = t->ulMaxSessionCount; s->MaxRWSession = t->ulMaxRwSessionCount; s->MinPinLen = t->ulMinPinLen; s->MaxPinLen = t->ulMaxPinLen; s->TotalPublicMemory = t->ulTotalPublicMemory; s->FreePublicMemory = t->ulFreePublicMemory; s->TotalPrivateMemory = t->ulTotalPrivateMemory; s->FreePrivateMemory = t->ulFreePrivateMemory; // Hardware version Format(buf, sizeof(buf), "%u.%02u", t->hardwareVersion.major, t->hardwareVersion.minor); s->HardwareVersion = CopyStr(buf); // Firmware version Format(buf, sizeof(buf), "%u.%02u", t->firmwareVersion.major, t->firmwareVersion.minor); s->FirmwareVersion = CopyStr(buf); return s; }
// Remove duplications from the token list TOKEN_LIST *UniqueToken(TOKEN_LIST *t) { UINT i, num, j, n; TOKEN_LIST *ret; // Validate arguments if (t == NULL) { return NULL; } num = 0; for (i = 0;i < t->NumTokens;i++) { bool exists = false; for (j = 0;j < i;j++) { if (StrCmpi(t->Token[j], t->Token[i]) == 0) { exists = true; break; } } if (exists == false) { num++; } } ret = ZeroMalloc(sizeof(TOKEN_LIST)); ret->Token = ZeroMalloc(sizeof(char *) * num); ret->NumTokens = num; n = 0; for (i = 0;i < t->NumTokens;i++) { bool exists = false; for (j = 0;j < i;j++) { if (StrCmpi(t->Token[j], t->Token[i]) == 0) { exists = true; break; } } if (exists == false) { ret->Token[n++] = CopyStr(t->Token[i]); } } return ret; }
// Open a secure device SECURE *OpenSec(UINT id) { SECURE_DEVICE *dev = GetSecureDevice(id); SECURE *sec; UINT err; if (dev == NULL) { return NULL; } sec = ZeroMalloc(sizeof(SECURE)); sec->lock = NewLock(); sec->Error = SEC_ERROR_NOERROR; sec->Dev = dev; // Get whether it's a ePass or not if (SearchStrEx(dev->DeviceName, "epass", 0, false) != INFINITE) { sec->IsEPass1000 = true; } // Load the module if (LoadSecModule(sec) == false) { CloseSec(sec); return NULL; } // Get the slot list sec->NumSlot = 0; if ((err = sec->Api->C_GetSlotList(true, NULL, &sec->NumSlot)) != CKR_OK || sec->NumSlot == 0) { // Failure FreeSecModule(sec); CloseSec(sec); return NULL; } sec->SlotIdList = (UINT *)ZeroMalloc(sizeof(UINT *) * sec->NumSlot); if (sec->Api->C_GetSlotList(TRUE, sec->SlotIdList, &sec->NumSlot) != CKR_OK) { // Failure Free(sec->SlotIdList); sec->SlotIdList = NULL; FreeSecModule(sec); CloseSec(sec); return NULL; } return sec; }
// Parse the token TOKEN_LIST *ParseToken(char *src, char *separator) { TOKEN_LIST *ret; char *tmp; char *str1, *str2; UINT len; UINT num; if (src == NULL) { ret = ZeroMalloc(sizeof(TOKEN_LIST)); ret->Token = ZeroMalloc(0); return ret; } if (separator == NULL) { separator = " ,\t\r\n"; } len = StrLen(src); str1 = Malloc(len + 1); str2 = Malloc(len + 1); StrCpy(str1, 0, src); StrCpy(str2, 0, src); Lock(token_lock); { tmp = strtok(str1, separator); num = 0; while (tmp != NULL) { num++; tmp = strtok(NULL, separator); } ret = Malloc(sizeof(TOKEN_LIST)); ret->NumTokens = num; ret->Token = (char **)Malloc(sizeof(char *) * num); num = 0; tmp = strtok(str2, separator); while (tmp != NULL) { ret->Token[num] = (char *)Malloc(StrLen(tmp) + 1); StrCpy(ret->Token[num], 0, tmp); num++; tmp = strtok(NULL, separator); } } Unlock(token_lock); Free(str1); Free(str2); return ret; }
// Initialize the packet adapter bool NullPaInit(SESSION *s) { NULL_LAN *n; static UINT id_seed = 0; // Validate arguments if (s == NULL) { return false; } id_seed++; n = ZeroMalloc(sizeof(NULL_LAN)); n->Id = id_seed; s->PacketAdapter->Param = (void *)n; n->Cancel = NewCancel(); n->PacketQueue = NewQueue(); n->Event = NewEvent(); NullGenerateMacAddress(n->MacAddr, n->Id, 0); n->PacketGeneratorThread = NewThread(NullPacketGenerateThread, n); return true; }
// Register in the ARP table void L3InsertArpTable(L3IF *f, UINT ip, UCHAR *mac) { L3ARPENTRY *a, t; // Validate arguments if (f == NULL || ip == 0 || ip == 0xffffffff || mac == NULL) { return; } Zero(&t, sizeof(t)); t.IpAddress = ip; a = Search(f->ArpTable, &t); if (a == NULL) { // Since this is not registered, register this a = ZeroMalloc(sizeof(L3ARPENTRY)); a->IpAddress = ip; Copy(a->MacAddress, mac, 6); Insert(f->ArpTable, a); } // Extend the expiration date a->Expire = Tick64() + ARP_ENTRY_EXPIRES; // Send waiting IP packets L3SendWaitingIp(f, mac, ip, a); }
// IPv6 拡張オプションヘッダ (可変長) の追加 void BuildAndAddIPv6PacketOptionHeader(BUF *b, IPV6_OPTION_HEADER *opt, UCHAR next_header, UINT size) { IPV6_OPTION_HEADER *h; UINT total_size; // 引数チェック if (b == NULL || opt == NULL) { return; } total_size = size; if ((total_size % 8) != 0) { total_size = ((total_size / 8) + 1) * 8; } h = ZeroMalloc(total_size); Copy(h, opt, size); h->Size = (total_size / 8) - 1; h->NextHeader = next_header; WriteBuf(b, h, total_size); Free(h); }
// Extract the license agreement from the EXE file wchar_t *ViExtractEula(char *exe) { BUF *b; UINT tmp_size; char *tmp; wchar_t *ret; // Validate arguments if (exe == NULL) { return false; } b = ViExtractResource(exe, RT_RCDATA, "LICENSE"); if (b == NULL) { return NULL; } tmp_size = b->Size + 1; tmp = ZeroMalloc(tmp_size); Copy(tmp, b->Buf, b->Size); FreeBuf(b); ret = CopyStrToUni(tmp); Free(tmp); return ret; }
// Convert the binary data to a hexadecimal string void BinToStr(char *str, UINT str_size, void *data, UINT data_size) { char *tmp; UCHAR *buf = (UCHAR *)data; UINT size; UINT i; // Validate arguments if (str == NULL || data == NULL) { if (str != NULL) { str[0] = 0; } return; } // Calculation of size size = data_size * 2 + 1; // Memory allocation tmp = ZeroMalloc(size); // Conversion for (i = 0;i < data_size;i++) { sprintf(&tmp[i * 2], "%02X", buf[i]); } // Copy StrCpy(str, str_size, tmp); // Memory release Free(tmp); }
// Set the connection settings UINT NtSetClientConfig(NAT *n, RPC_CREATE_LINK *t) { Lock(n->lock); { if (n->ClientOption != NULL || n->ClientAuth != NULL) { Free(n->ClientOption); CiFreeClientAuth(n->ClientAuth); } n->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION)); Copy(n->ClientOption, t->ClientOption, sizeof(CLIENT_OPTION)); n->ClientAuth = CopyClientAuth(t->ClientAuth); } Unlock(n->lock); NiWriteConfig(n); if (n->Online) { NtOffline(n, NULL); NtOnline(n, NULL); } return ERR_NO_ERROR; }
// バイナリデータを 16 進文字列に変換する void BinToStr(char *str, UINT str_size, void *data, UINT data_size) { char *tmp; UCHAR *buf = (UCHAR *)data; UINT size; UINT i; // 引数チェック if (str == NULL || data == NULL) { if (str != NULL) { str[0] = 0; } return; } // サイズの計算 size = data_size * 2 + 1; // メモリ確保 tmp = ZeroMalloc(size); // 変換 for (i = 0;i < data_size;i++) { sprintf(&tmp[i * 2], "%02X", buf[i]); } // コピー StrCpy(str, str_size, tmp); // メモリ解放 Free(tmp); }
// Create new VPN Azure client AZURE_CLIENT *NewAzureClient(CEDAR *cedar, SERVER *server) { AZURE_CLIENT *ac; // Validate arguments if (cedar == NULL || server == NULL) { return NULL; } ac = ZeroMalloc(sizeof(AZURE_CLIENT)); ac->Cedar = cedar; ac->Server = server; ac->Lock = NewLock(); ac->IsEnabled = false; ac->Event = NewEvent(); // Start main thread ac->MainThread = NewThread(AcMainThread, ac); return ac; }
// バイナリデータを 16 進文字列に変換する (スペースも入れる) void BinToStrEx(char *str, UINT str_size, void *data, UINT data_size) { char *tmp; UCHAR *buf = (UCHAR *)data; UINT size; UINT i; // 引数チェック if (str == NULL || data == NULL) { return; } // サイズの計算 size = data_size * 3 + 1; // メモリ確保 tmp = ZeroMalloc(size); // 変換 for (i = 0;i < data_size;i++) { Format(&tmp[i * 3], 0, "%02X ", buf[i]); } Trim(tmp); // コピー StrCpy(str, str_size, tmp); // メモリ解放 Free(tmp); }
void BinToStrEx2(char *str, UINT str_size, void *data, UINT data_size, char padding_char) { char *tmp; UCHAR *buf = (UCHAR *)data; UINT size; UINT i; // 引数チェック if (str == NULL || data == NULL) { return; } // サイズの計算 size = data_size * 3 + 1; // メモリ確保 tmp = ZeroMalloc(size); // 変換 for (i = 0;i < data_size;i++) { Format(&tmp[i * 3], 0, "%02X%c", buf[i], padding_char); } if (StrLen(tmp) >= 1) { if (tmp[StrLen(tmp) - 1] == padding_char) { tmp[StrLen(tmp) - 1] = 0; } } // コピー StrCpy(str, str_size, tmp); // メモリ解放 Free(tmp); }
// Create a SSTP server SSTP_SERVER *NewSstpServer(CEDAR *cedar, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, SOCK_EVENT *se, char *client_host_name, char *crypt_name) { SSTP_SERVER *s = ZeroMalloc(sizeof(SSTP_SERVER)); s->LastRecvTick = Tick64(); StrCpy(s->ClientHostName, sizeof(s->ClientHostName), client_host_name); StrCpy(s->ClientCipherName, sizeof(s->ClientCipherName), crypt_name); s->Cedar = cedar; AddRef(s->Cedar->ref); NewTubePair(&s->TubeSend, &s->TubeRecv, 0); SetTubeSockEvent(s->TubeSend, se); s->Now = Tick64(); Copy(&s->ClientIp, client_ip, sizeof(IP)); s->ClientPort = client_port; Copy(&s->ServerIp, server_ip, sizeof(IP)); s->ServerPort = server_port; s->SockEvent = se; AddRef(s->SockEvent->ref); s->RecvQueue = NewQueueFast(); s->SendQueue = NewQueueFast(); s->Interrupt = NewInterruptManager(); return s; }
// RPC_ENUM_NAT void InRpcEnumNat(RPC_ENUM_NAT *t, PACK *p) { UINT i; // Validate arguments if (t == NULL || p == NULL) { return; } Zero(t, sizeof(RPC_ENUM_NAT)); t->NumItem = PackGetInt(p, "NumItem"); PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName)); t->Items = ZeroMalloc(sizeof(RPC_ENUM_NAT_ITEM) * t->NumItem); for (i = 0;i < t->NumItem;i++) { RPC_ENUM_NAT_ITEM *e = &t->Items[i]; e->Id = PackGetIntEx(p, "Id", i); e->Protocol = PackGetIntEx(p, "Protocol", i); e->SrcIp = PackGetIntEx(p, "SrcIp", i); PackGetStrEx(p, "SrcHost", e->SrcHost, sizeof(e->SrcHost), i); e->SrcPort = PackGetIntEx(p, "SrcPort", i); e->DestIp = PackGetIntEx(p, "DestIp", i); PackGetStrEx(p, "DestHost", e->DestHost, sizeof(e->DestHost), i); e->DestPort = PackGetIntEx(p, "DestPort", i); e->CreatedTime = PackGetInt64Ex(p, "CreatedTime", i); e->LastCommTime = PackGetInt64Ex(p, "LastCommTime", i); e->SendSize = PackGetInt64Ex(p, "SendSize", i); e->RecvSize = PackGetInt64Ex(p, "RecvSize", i); e->TcpStatus = PackGetIntEx(p, "TcpStatus", i); } }
// RPC_ENUM_DHCP void InRpcEnumDhcp(RPC_ENUM_DHCP *t, PACK *p) { UINT i; // Validate arguments if (t == NULL || p == NULL) { return; } Zero(t, sizeof(RPC_ENUM_DHCP)); t->NumItem = PackGetInt(p, "NumItem"); t->Items = ZeroMalloc(sizeof(RPC_ENUM_DHCP_ITEM) * t->NumItem); PackGetStr(p, "HubName", t->HubName, sizeof(t->HubName)); for (i = 0;i < t->NumItem;i++) { RPC_ENUM_DHCP_ITEM *e = &t->Items[i]; e->Id = PackGetIntEx(p, "Id", i); e->LeasedTime = PackGetInt64Ex(p, "LeasedTime", i); e->ExpireTime = PackGetInt64Ex(p, "ExpireTime", i); PackGetDataEx2(p, "MacAddress", e->MacAddress, 6, i); e->IpAddress = PackGetIp32Ex(p, "IpAddress", i); e->Mask = PackGetIntEx(p, "Mask", i); PackGetStrEx(p, "Hostname", e->Hostname, sizeof(e->Hostname), i); } }
// Issue an ARP query void L3SendArp(L3IF *f, UINT ip) { L3ARPWAIT t, *w; // Validate arguments if (f == NULL || ip == 0 || ip == 0xffffffff) { return; } // Examine whether it has not already registered Zero(&t, sizeof(t)); t.IpAddress = ip; w = Search(f->ArpWaitTable, &t); if (w != NULL) { // Do not do anything because it is already registered in the waiting list return; } else { // Register in the waiting list newly w = ZeroMalloc(sizeof(L3ARPWAIT)); w->Expire = Tick64() + ARP_REQUEST_GIVEUP; w->IpAddress = ip; Insert(f->ArpWaitTable, w); } }
// 64bit 整数のためのフォーマット文字列を置換する char *ReplaceFormatStringFor64(char *fmt) { char *tmp; char *ret; UINT tmp_size; // 引数チェック if (fmt == NULL) { return NULL; } tmp_size = StrSize(fmt) * 2; tmp = ZeroMalloc(tmp_size); #ifdef OS_WIN32 ReplaceStrEx(tmp, tmp_size, fmt, "%ll", "%I64", false); #else // OS_WIN32 ReplaceStrEx(tmp, tmp_size, fmt, "%I64", "%ll", false); #endif // OS_WIN32 ret = CopyStr(tmp); Free(tmp); return ret; }
// Send an L2 packet immediately void L3SendL2Now(L3IF *f, UCHAR *dest_mac, UCHAR *src_mac, USHORT protocol, void *data, UINT size) { UCHAR *buf; MAC_HEADER *mac_header; PKT *p; // Validate arguments if (f == NULL || dest_mac == NULL || src_mac == NULL || data == NULL) { return; } // Buffer creation buf = Malloc(MAC_HEADER_SIZE + size); // MAC header mac_header = (MAC_HEADER *)&buf[0]; Copy(mac_header->DestAddress, dest_mac, 6); Copy(mac_header->SrcAddress, src_mac, 6); mac_header->Protocol = Endian16(protocol); // Copy data Copy(&buf[sizeof(MAC_HEADER)], data, size); // Size size += sizeof(MAC_HEADER); // Packet generation p = ZeroMalloc(sizeof(PKT)); p->PacketData = buf; p->PacketSize = size; // Add to the queue InsertQueue(f->SendQueue, p); }
// チェックサム計算 USHORT CalcChecksumForIPv6(IPV6_ADDR *src_ip, IPV6_ADDR *dest_ip, UCHAR protocol, void *data, UINT size) { UCHAR *tmp; UINT tmp_size; IPV6_PSEUDO_HEADER *ph; USHORT ret; // 引数チェック if (data == NULL && size != 0) { return 0; } tmp_size = size + sizeof(IPV6_PSEUDO_HEADER); tmp = ZeroMalloc(tmp_size); ph = (IPV6_PSEUDO_HEADER *)tmp; Copy(&ph->SrcAddress, src_ip, sizeof(IPV6_ADDR)); Copy(&ph->DestAddress, dest_ip, sizeof(IPV6_ADDR)); ph->UpperLayerPacketSize = Endian32(size); ph->NextHeader = protocol; Copy(((UCHAR *)tmp) + sizeof(IPV6_PSEUDO_HEADER), data, size); ret = IpChecksum(tmp, tmp_size); Free(tmp); return ret; }
void BinToStrEx2(char *str, UINT str_size, void *data, UINT data_size, char padding_char) { char *tmp; UCHAR *buf = (UCHAR *)data; UINT size; UINT i; // Validate arguments if (str == NULL || data == NULL) { return; } // Calculation of size size = data_size * 3 + 1; // Memory allocation tmp = ZeroMalloc(size); // Conversion for (i = 0;i < data_size;i++) { Format(&tmp[i * 3], 0, "%02X%c", buf[i], padding_char); } if (StrLen(tmp) >= 1) { if (tmp[StrLen(tmp) - 1] == padding_char) { tmp[StrLen(tmp) - 1] = 0; } } // Copy StrCpy(str, str_size, tmp); // Memory release Free(tmp); }
// Enumerate all devices UINT EtEnumAllDevice(EL *e, RPC_ENUM_DEVICE *t) { TOKEN_LIST *eth; UINT i; if (IsEthSupported() == false) { return ERR_NOT_SUPPORTED; } FreeRpcEnumDevice(t); Zero(t, sizeof(RPC_ENUM_DEVICE)); eth = GetEthList(); t->NumItem = eth->NumTokens; t->Items = ZeroMalloc(sizeof(RPC_ENUM_DEVICE_ITEM) * t->NumItem); for (i = 0;i < eth->NumTokens;i++) { char *name = eth->Token[i]; RPC_ENUM_DEVICE_ITEM *item = &t->Items[i]; StrCpy(item->DeviceName, sizeof(item->DeviceName), name); } FreeToken(eth); return ERR_NO_ERROR; }
// Create new traffic size object TRAFFIC *NewTraffic() { TRAFFIC *t; t = ZeroMalloc(sizeof(TRAFFIC)); return t; }
// Create a new SecureNAT SNAT *SnNewSecureNAT(HUB *h, VH_OPTION *o) { SNAT *s; THREAD *t; // Validate arguments if (h == NULL || o == NULL) { return NULL; } s = ZeroMalloc(sizeof(SNAT)); s->Cedar = h->Cedar; s->Hub = h; s->lock = NewLock(); // Create a NAT s->Nat = NiNewNatEx(s, o); // Initialize the virtual machine VirtualInit(s->Nat->Virtual); // Create a thread t = NewThread(SnSecureNATThread, s); WaitThreadInit(t); ReleaseThread(t); return s; }
// Create the EL EL *NewEl() { EL *e; #ifdef OS_WIN32 RegistWindowsFirewallAll(); #endif e = ZeroMalloc(sizeof(EL)); e->lock = NewLock(); e->ref = NewRef(); e->Cedar = NewCedar(NULL, NULL); // Ethernet initialization InitEth(); // Setting initialization ElInitConfig(e); // Listener start ElStartListener(e); // Initialize the license status ElParseCurrentLicenseStatus(e->LicenseSystem, e->LicenseStatus); // Eraser start e->Eraser = NewEraser(NULL, e->AutoDeleteCheckDiskFreeSpaceMin); return e; }
// Read the string table void ViLoadStringTables() { UINT i, n; HINSTANCE hInst = GetModuleHandle(NULL); string_table = NewList(ViCompareString); n = 0; for (i = 1;;i++) { wchar_t *str = ViLoadString(hInst, i); if (str != NULL) { VI_STRING *s; n = 0; s = ZeroMalloc(sizeof(VI_STRING)); s->Id = i; s->String = str; s->StringA = CopyUniToStr(str); Insert(string_table, s); } else { n++; if (n >= 1500) { break; } } } }
// Device enumeration UINT EtEnumDevice(EL *e, RPC_ENUM_DEVICE *t) { bool is_beta_expired = ElIsBetaExpired(); if (is_beta_expired) { // The beta version has expired return ERR_BETA_EXPIRES; } FreeRpcEnumDevice(t); Zero(t, sizeof(RPC_ENUM_DEVICE)); LockList(e->DeviceList); { UINT i; t->NumItem = LIST_NUM(e->DeviceList); t->Items = ZeroMalloc(sizeof(RPC_ENUM_DEVICE_ITEM) * t->NumItem); for (i = 0;i < t->NumItem;i++) { RPC_ENUM_DEVICE_ITEM *d = &t->Items[i]; EL_DEVICE *eld = LIST_DATA(e->DeviceList, i); StrCpy(d->DeviceName, sizeof(d->DeviceName), eld->DeviceName); d->Active = eld->Active && ((ELOG_IS_BETA || e->LicenseStatus->Valid) ? true : false); } } UnlockList(e->DeviceList); return ERR_NO_ERROR; }
// ICMPv6 パケットの送信 BUF *BuildICMPv6(IPV6_ADDR *src_ip, IPV6_ADDR *dest_ip, UCHAR hop_limit, UCHAR type, UCHAR code, void *data, UINT size, UINT id) { ICMP_HEADER *icmp; void *data_buf; BUF *ret; // 引数チェック if (src_ip == NULL || dest_ip == NULL || data == NULL) { return NULL; } // ヘッダの組み立て icmp = ZeroMalloc(sizeof(ICMP_HEADER) + size); data_buf = ((UCHAR *)icmp) + sizeof(ICMP_HEADER); Copy(data_buf, data, size); icmp->Type = type; icmp->Code = code; icmp->Checksum = CalcChecksumForIPv6(src_ip, dest_ip, IP_PROTO_ICMPV6, icmp, sizeof(ICMP_HEADER) + size); ret = BuildIPv6(dest_ip, src_ip, id, IP_PROTO_ICMPV6, hop_limit, icmp, sizeof(ICMP_HEADER) + size); Free(icmp); return ret; }