質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

コンパイラ

コンパイラは、プログラミング言語で記述したソースコードを、コンピュータの実行形式であるオブジェクトコードに変換するプログラムです。

Q&A

解決済

2回答

8133閲覧

互換性のないポインタの警告を解消したい

yhi

総合スコア5

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

コンパイラ

コンパイラは、プログラミング言語で記述したソースコードを、コンピュータの実行形式であるオブジェクトコードに変換するプログラムです。

0グッド

0クリップ

投稿2019/11/19 07:48

前提・実現したいこと

プログラミング初心者で、Arduinoから入って、ESP32のプログラミングに挑戦しています。
esp-idfでbtstackを使ってみて、ビルドは成功したのですが、includeしているdhserver.cというファイルで警告が出ました。
エラーメッセージから、ポインタの互換性が無いということが分かり、ネットで調べたりもしましたが、解決方法がよくわかりませんでした。
このまま放置しても問題はなさそうなのですが、解消できるならしたいので、どなたかご教授頂けませんでしょうか。
宜しくお願い致します。

発生している問題・エラーメッセージ

「err_t dhserv_init(dhcp_config_t *c)」の中にある
「udp_recv(pcb, udp_recv_proc, NULL);」の
「udp_recv_proc」の部分に波線がついて警告が出ています。

passing argument 2 of 'udp_recv' from incompatible pointer type [-Wincompatible-pointer-types]

該当のソースコード

c

1/* 2 * The MIT License (MIT) 3 * 4 * Copyright (c) 2015 by Sergey Fetisov <fsenok@gmail.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in all 14 * copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25#include "dhserver.h" 26 27/* DHCP message type */ 28#define DHCP_DISCOVER 1 29#define DHCP_OFFER 2 30#define DHCP_REQUEST 3 31#define DHCP_DECLINE 4 32#define DHCP_ACK 5 33#define DHCP_NAK 6 34#define DHCP_RELEASE 7 35#define DHCP_INFORM 8 36 37/* DHCP options */ 38enum DHCP_OPTIONS 39{ 40 DHCP_PAD = 0, 41 DHCP_SUBNETMASK = 1, 42 DHCP_ROUTER = 3, 43 DHCP_DNSSERVER = 6, 44 DHCP_HOSTNAME = 12, 45 DHCP_DNSDOMAIN = 15, 46 DHCP_MTU = 26, 47 DHCP_BROADCAST = 28, 48 DHCP_PERFORMROUTERDISC = 31, 49 DHCP_STATICROUTE = 33, 50 DHCP_NISDOMAIN = 40, 51 DHCP_NISSERVER = 41, 52 DHCP_NTPSERVER = 42, 53 DHCP_VENDOR = 43, 54 DHCP_IPADDRESS = 50, 55 DHCP_LEASETIME = 51, 56 DHCP_OPTIONSOVERLOADED = 52, 57 DHCP_MESSAGETYPE = 53, 58 DHCP_SERVERID = 54, 59 DHCP_PARAMETERREQUESTLIST = 55, 60 DHCP_MESSAGE = 56, 61 DHCP_MAXMESSAGESIZE = 57, 62 DHCP_RENEWALTIME = 58, 63 DHCP_REBINDTIME = 59, 64 DHCP_CLASSID = 60, 65 DHCP_CLIENTID = 61, 66 DHCP_USERCLASS = 77, /* RFC 3004 */ 67 DHCP_FQDN = 81, 68 DHCP_DNSSEARCH = 119, /* RFC 3397 */ 69 DHCP_CSR = 121, /* RFC 3442 */ 70 DHCP_MSCSR = 249, /* MS code for RFC 3442 */ 71 DHCP_END = 255 72}; 73 74typedef struct 75{ 76 uint8_t dp_op; /* packet opcode type */ 77 uint8_t dp_htype; /* hardware addr type */ 78 uint8_t dp_hlen; /* hardware addr length */ 79 uint8_t dp_hops; /* gateway hops */ 80 uint32_t dp_xid; /* transaction ID */ 81 uint16_t dp_secs; /* seconds since boot began */ 82 uint16_t dp_flags; 83 uint8_t dp_ciaddr[4]; /* client IP address */ 84 uint8_t dp_yiaddr[4]; /* 'your' IP address */ 85 uint8_t dp_siaddr[4]; /* server IP address */ 86 uint8_t dp_giaddr[4]; /* gateway IP address */ 87 uint8_t dp_chaddr[16]; /* client hardware address */ 88 uint8_t dp_legacy[192]; 89 uint8_t dp_magic[4]; 90 uint8_t dp_options[275]; /* options area */ 91} DHCP_TYPE; 92 93DHCP_TYPE dhcp_data; 94static struct udp_pcb *pcb = NULL; 95static dhcp_config_t *config = NULL; 96 97char magic_cookie[] = {0x63,0x82,0x53,0x63}; 98 99static dhcp_entry_t *entry_by_ip(uint32_t ip) 100{ 101 int i; 102 for (i = 0; i < config->num_entry; i++) 103 if (*(uint32_t *)config->entries[i].addr == ip) 104 return &config->entries[i]; 105 return NULL; 106} 107 108static dhcp_entry_t *entry_by_mac(uint8_t *mac) 109{ 110 int i; 111 for (i = 0; i < config->num_entry; i++) 112 if (memcmp(config->entries[i].mac, mac, 6) == 0) 113 return &config->entries[i]; 114 return NULL; 115} 116 117static __inline bool is_vacant(dhcp_entry_t *entry) 118{ 119 return memcmp("\0\0\0\0\0", entry->mac, 6) == 0; 120} 121 122static dhcp_entry_t *vacant_address(void) 123{ 124 int i; 125 for (i = 0; i < config->num_entry; i++) 126 if (is_vacant(config->entries + i)) 127 return config->entries + i; 128 return NULL; 129} 130 131static __inline void free_entry(dhcp_entry_t *entry) 132{ 133 memset(entry->mac, 0, 6); 134} 135 136static uint8_t *find_dhcp_option(uint8_t *attrs, int size, uint8_t attr) 137{ 138 int i = 0; 139 while ((i + 1) < size) 140 { 141 int next = i + attrs[i + 1] + 2; 142 if (next > size) return NULL; 143 if (attrs[i] == attr) 144 return attrs + i; 145 i = next; 146 } 147 return NULL; 148} 149 150static int fill_options(void *dest, 151 uint8_t msg_type, 152 const char *domain, 153 uint32_t dns, 154 int lease_time, 155 uint32_t serverid, 156 uint32_t router, 157 uint32_t subnet) 158{ 159 uint8_t *ptr = (uint8_t *)dest; 160 /* ACK message type */ 161 *ptr++ = 53; 162 *ptr++ = 1; 163 *ptr++ = msg_type; 164 165 /* dhcp server identifier */ 166 *ptr++ = DHCP_SERVERID; 167 *ptr++ = 4; 168 *(uint32_t *)ptr = serverid; 169 ptr += 4; 170 171 /* lease time */ 172 *ptr++ = DHCP_LEASETIME; 173 *ptr++ = 4; 174 *ptr++ = (lease_time >> 24) & 0xFF; 175 *ptr++ = (lease_time >> 16) & 0xFF; 176 *ptr++ = (lease_time >> 8) & 0xFF; 177 *ptr++ = (lease_time >> 0) & 0xFF; 178 179 /* subnet mask */ 180 *ptr++ = DHCP_SUBNETMASK; 181 *ptr++ = 4; 182 *(uint32_t *)ptr = subnet; 183 ptr += 4; 184 185 /* router */ 186 if (router != 0) 187 { 188 *ptr++ = DHCP_ROUTER; 189 *ptr++ = 4; 190 *(uint32_t *)ptr = router; 191 ptr += 4; 192 } 193 194 /* domain name */ 195 if (domain != NULL) 196 { 197 int len = strlen(domain); 198 *ptr++ = DHCP_DNSDOMAIN; 199 *ptr++ = len; 200 memcpy(ptr, domain, len); 201 ptr += len; 202 } 203 204 /* domain name server (DNS) */ 205 if (dns != 0) 206 { 207 *ptr++ = DHCP_DNSSERVER; 208 *ptr++ = 4; 209 *(uint32_t *)ptr = dns; 210 ptr += 4; 211 } 212 213 /* end */ 214 *ptr++ = DHCP_END; 215 return ptr - (uint8_t *)dest; 216} 217 218static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const struct ip4_addr *addr, u16_t port) 219{ 220 (void) arg; 221 (void) addr; 222 223 uint8_t *ptr; 224 dhcp_entry_t *entry; 225 struct pbuf *pp; 226 227 unsigned int n = p->len; 228 if (n > sizeof(dhcp_data)) n = sizeof(dhcp_data); 229 memcpy(&dhcp_data, p->payload, n); 230 switch (dhcp_data.dp_options[2]) 231 { 232 case DHCP_DISCOVER: 233 entry = entry_by_mac(dhcp_data.dp_chaddr); 234 if (entry == NULL) entry = vacant_address(); 235 if (entry == NULL) break; 236 237 dhcp_data.dp_op = 2; /* reply */ 238 dhcp_data.dp_secs = 0; 239 dhcp_data.dp_flags = 0; 240 *(uint32_t *)dhcp_data.dp_yiaddr = *(uint32_t *)entry->addr; 241 memcpy(dhcp_data.dp_magic, magic_cookie, 4); 242 243 memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); 244 245 fill_options(dhcp_data.dp_options, 246 DHCP_OFFER, 247 config->domain, 248 *(uint32_t *)config->dns, 249 entry->lease, 250 *(uint32_t *)config->addr, 251 *(uint32_t *)config->addr, 252 *(uint32_t *)entry->subnet); 253 254 pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); 255 if (pp == NULL) break; 256 memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); 257 udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); 258 pbuf_free(pp); 259 break; 260 261 case DHCP_REQUEST: 262 /* 1. find requested ipaddr in option list */ 263 ptr = find_dhcp_option(dhcp_data.dp_options, sizeof(dhcp_data.dp_options), DHCP_IPADDRESS); 264 if (ptr == NULL) break; 265 if (ptr[1] != 4) break; 266 ptr += 2; 267 268 /* 2. does hw-address registered? */ 269 entry = entry_by_mac(dhcp_data.dp_chaddr); 270 if (entry != NULL) free_entry(entry); 271 272 /* 3. find requested ipaddr */ 273 entry = entry_by_ip(*(uint32_t *)ptr); 274 if (entry == NULL) break; 275 if (!is_vacant(entry)) break; 276 277 /* 4. fill struct fields */ 278 memcpy(dhcp_data.dp_yiaddr, ptr, 4); 279 dhcp_data.dp_op = 2; /* reply */ 280 dhcp_data.dp_secs = 0; 281 dhcp_data.dp_flags = 0; 282 memcpy(dhcp_data.dp_magic, magic_cookie, 4); 283 284 /* 5. fill options */ 285 memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options)); 286 287 fill_options(dhcp_data.dp_options, 288 DHCP_ACK, 289 config->domain, 290 *(uint32_t *)config->dns, 291 entry->lease, 292 *(uint32_t *)config->addr, 293 *(uint32_t *)config->addr, 294 *(uint32_t *)entry->subnet); 295 296 /* 6. send ACK */ 297 pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL); 298 if (pp == NULL) break; 299 memcpy(entry->mac, dhcp_data.dp_chaddr, 6); 300 memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data)); 301 udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port); 302 pbuf_free(pp); 303 break; 304 305 default: 306 break; 307 } 308 pbuf_free(p); 309} 310 311err_t dhserv_init(dhcp_config_t *c) 312{ 313 err_t err; 314 // udp_init(); already called from lwip_init 315 dhserv_free(); 316 pcb = udp_new(); 317 if (pcb == NULL) 318 return ERR_MEM; 319 err = udp_bind(pcb, IP_ADDR_ANY, c->port); 320 if (err != ERR_OK) 321 { 322 dhserv_free(); 323 return err; 324 } 325 udp_recv(pcb, udp_recv_proc, NULL); 326 config = c; 327 return ERR_OK; 328} 329 330void dhserv_free(void) 331{ 332 if (pcb == NULL) return; 333 udp_remove(pcb); 334 pcb = NULL; 335}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

udp_recv の型はこのようになっています。

c

void udp_recv (struct udp_pcb *pcb , err_t (*recv) (void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port) , void *recv_arg );

つまり、 udp_recv が受け取る関数ポインタの型は err_t (*)(void*, struct udp_pcb*, struct pbuf *, struct ip_addr *, u16_t) であることを意味します。

しかし実際に渡している udp_recv_proc の型は void (*)(void *, struct udp_pcb*, struct pbuf *, const struct ip4_addr*, u16_t) です。

要求に対して異なる型のポインタを渡しているという意味でエラーが出ているので、 udp_recv_proc が要求どおりになるように修正するのが最もまともな修正方法です。

関数ポインタを他の関数ポインタに変換して呼び出しを試みた場合にその挙動は言語仕様上は未定義です。 実際はある程度は上手く動きますが、場合によってはスタックが無茶苦茶に壊れて暴走するなどの可能性もあります。 どのようにコンパイルされるのか、 ABI について充分に理解できている場合を除いては型が一致するようにするのが無難です。

投稿2019/11/19 08:21

SaitoAtsushi

総合スコア5444

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yhi

2019/11/19 08:29

回答ありがとうございます。 こんな複雑なプログラムを扱うのは初めてでしたので、教えていただき、とても勉強になりました。 ありがとうございました!
guest

0

ベストアンサー

コードが正しいかどうかというのは別として、

udp_recv(pcb, (void*)udp_recv_proc, NULL);

としてみればどうでしょう

投稿2019/11/19 08:05

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yhi

2019/11/19 08:26

回答ありがとうございます。 教えていただいた通りに修正し、フルビルドし直したところ、警告は消え、ビルドも無事に成功しました。 ありがとうございました!
y_waiwai

2019/11/19 08:35

これで警告は消えます。 が、あくまで警告が出ないように細工してるだけで、これが「正しい」とは限らないので注意しましょう
yhi

2019/11/19 13:26

わかりました、今後、何か問題が起こったらここを疑ってみることにします。 ご親切にありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問