Code Monkey home page Code Monkey logo

iso14229's Introduction

iso14229

Build Status

iso14229 is an implementation of UDS (ISO14229) targeting embedded systems. It is tested with isotp-c as well as linux kernel ISO15765-2 (ISO-TP) transport layer implementations.

API status: not yet stable.

Using this library

  1. Download iso14229.zip from the releases page, copy iso14229.c and iso14229.h into your source tree and build.
  2. Look at the examples

Build Systems

iso14229 is designed to build on any platform.

Preprocessor Defines

Define Description Valid values
-DUDS_TP_ISOTP_C build the isotp-c transport layer (recommended for bare-metal systems) on/off
-DUDS_TP_ISOTP_SOCK build the isotp socket transport layer (recommended for linux) on/off
-DUDS_TP_ISOTP_C_SOCKETCAN build the isotp-c transport layer with socketcan support (linux-only) on/off
UDS_... Additional configuration options see src/config.h
UDS_SYS Selects target system see src/sys.h

Features

  • entirely static memory allocation. (no malloc, calloc, ...)
  • highly portable and tested
    • architectures: arm, x86-64, ppc, ppc64, risc
    • systems: linux, Windows, esp32, Arduino, NXP s32k
    • transports: isotp-c, linux isotp sockets

supported functions (server and client )

SID name supported
0x10 diagnostic session control
0x11 ECU reset
0x14 clear diagnostic information
0x19 read DTC information
0x22 read data by identifier
0x23 read memory by address
0x24 read scaling data by identifier
0x27 security access
0x28 communication control
0x2A read periodic data by identifier
0x2C dynamically define data identifier
0x2E write data by identifier
0x2F input control by identifier
0x31 routine control
0x34 request download
0x35 request upload
0x36 transfer data
0x37 request transfer exit
0x38 request file transfer
0x3D write memory by address
0x3E tester present
0x83 access timing parameter
0x84 secured data transmission
0x85 control DTC setting
0x86 response on event

Running Tests

See test_all.sh and test/README.md

Documentation

Server Events

see enum UDSServerEvent in src/uds.h

UDS_SRV_EVT_DiagSessCtrl (0x10)

Arguments

typedef struct {
    const enum UDSDiagnosticSessionType type; /**< requested session type */
    uint16_t p2_ms;                           /**< optional return value: p2 timing override */
    uint32_t p2_star_ms;                      /**< optional return value: p2* timing override */
} UDSDiagSessCtrlArgs_t;

Supported Responses

Value enum Meaning
0x00 kPositiveResponse Request to change diagnostic level accepted.
0x12 kSubFunctionNotSupported The server doesn't support this diagnostic level
0x22 kConditionsNotCorrect The server can't/won't transition to the specified diagnostic level at this time

UDS_SRV_EVT_ECUReset (0x11)

Arguments

typedef struct {
    const enum UDSECUResetType type; /**< reset type requested by client */
    uint8_t powerDownTime; /**< Optional response: notify client of time until shutdown (0-254) 255
                              indicates that a time is not available. */
} UDSECUResetArgs_t;

Supported Responses

Value enum Meaning
0x00 kPositiveResponse Request to reset ECU accepted.
0x12 kSubFunctionNotSupported The server doesn't support the specified type of ECU reset
0x22 kConditionsNotCorrect The server can't reset now
0x33 kSecurityAccessDenied The current level of security access doesn't permit this type of ECU reset

UDS_SRV_EVT_ReadDataByIdent (0x22)

Arguments

typedef struct {
    const uint16_t dataId; /*! data identifier */
    /*! function for copying to the server send buffer. Returns `kPositiveResponse` on success and `kResponseTooLong` if the length of the data to be copied exceeds that of the server send buffer */
    const uint8_t (*copy)(UDSServer_t *srv, const void *src,
                    uint16_t count); 
} UDSRDBIArgs_t;

Supported Responses

Value enum Meaning
0x00 kPositiveResponse Request to read data accepted (be sure to call copy(...))
0x14 kResponseTooLong The total length of the response message exceeds the transport buffer size
0x31 kRequestOutOfRange The requested data identifer isn't supported
0x33 kSecurityAccessDenied The current level of security access doesn't permit reading the requested data identifier

UDS_SRV_EVT_SecAccessRequestSeed, UDS_SRV_EVT_SecAccessValidateKey (0x27)

Arguments

typedef struct {
    const uint8_t level;             /*! requested security level */
    const uint8_t *const dataRecord; /*! pointer to request data */
    const uint16_t len;              /*! size of request data */
    /*! function for copying to the server send buffer. Returns `kPositiveResponse` on success and `kResponseTooLong` if the length of the data to be copied exceeds that of the server send buffer */
    uint8_t (*copySeed)(UDSServer_t *srv, const void *src,
                        uint16_t len);
} UDSSecAccessRequestSeedArgs_t;

typedef struct {
    const uint8_t level;      /*! security level to be validated */
    const uint8_t *const key; /*! key sent by client */
    const uint16_t len;       /*! length of key */
} UDSSecAccessValidateKeyArgs_t;

Supported Responses

Value enum Meaning
0x00 kPositiveResponse Request accepted
0x12 kSubFunctionNotSupported The requested security level is not supported
0x22 kConditionsNotCorrect The server can't handle the request right now
0x31 kRequestOutOfRange The dataRecord contains invalid data
0x35 kInvalidKey The key doesn't match
0x36 kExceededNumberOfAttempts False attempt limit reached
0x37 kRequiredTimeDelayNotExpired RequestSeed request received and delay timer is still active

UDS_SRV_EVT_CommCtrl (0x28)

Arguments

typedef struct {
    enum UDSCommunicationControlType ctrlType; 
    enum UDSCommunicationType commType;
} UDSCommCtrlArgs_t;

Supported Responses

Value enum Meaning
0x00 kPositiveResponse Request accepted
0x12 kSubFunctionNotSupported The requested control type is not supported
0x22 kConditionsNotCorrect The server can't enable/disable the selected communication type now
0x31 kRequestOutOfRange The requested control type or communication type is erroneous

UDS_SRV_EVT_WriteDataByIdent (0x2E)

Arguments

typedef struct {
    const uint16_t dataId;     /*! WDBI Data Identifier */
    const uint8_t *const data; /*! pointer to data */
    const uint16_t len;        /*! length of data */
} UDSWDBIArgs_t;

Supported Responses

Value enum Meaning
0x00 kPositiveResponse Request to write data accepted
0x22 kConditionsNotCorrect The server can't write this data now
0x31 kRequestOutOfRange The requested data identifer isn't supported or the data is invalid
0x33 kSecurityAccessDenied The current level of security access doesn't permit writing to the requested data identifier
0x72 kGeneralProgrammingFailure Memory write failed

UDS_SRV_EVT_RoutineCtrl (0x31)

Arguments

typedef struct {
    const uint8_t ctrlType;      /*! routineControlType */
    const uint16_t id;           /*! routineIdentifier */
    const uint8_t *optionRecord; /*! optional data */
    const uint16_t len;          /*! length of optional data */
    /*! function for copying to the server send buffer. Returns `kPositiveResponse` on success and `kResponseTooLong` if the length of the data to be copied exceeds that of the server send buffer */
    uint8_t (*copyStatusRecord)(UDSServer_t *srv, const void *src,
                                uint16_t len);
} UDSRoutineCtrlArgs_t;

Supported Responses

Value enum Meaning
0x00 kPositiveResponse Request accepted
0x22 kConditionsNotCorrect The server can't perform this operation now
0x24 kRequestSequenceError Stop requested but routine hasn't started. Start requested but routine has already started (optional). Results are not available becuase routine has never started.
0x31 kRequestOutOfRange The requested routine identifer isn't supported or the optionRecord is invalid
0x33 kSecurityAccessDenied The current level of security access doesn't permit this operation
0x72 kGeneralProgrammingFailure internal memory operation failed (e.g. erasing flash)

UDS_SRV_EVT_RequestDownload (0x34)

Arguments

typedef struct {
    const void *addr;                   /*! requested address */
    const size_t size;                  /*! requested download size */
    const uint8_t dataFormatIdentifier; /*! optional specifier for format of data */
    uint16_t maxNumberOfBlockLength; /*! response: inform client how many data bytes to send in each
                                        `TransferData` request */
} UDSRequestDownloadArgs_t;

Supported Responses

Value enum Meaning
0x00 kPositiveResponse Request accepted
0x22 kConditionsNotCorrect The server can't perform this operation now
0x31 kRequestOutOfRange dataFormatIdentifier invalid, addr or size invalid
0x33 kSecurityAccessDenied The current level of security access doesn't permit this operation
0x34 kAuthenticationRequired Client rights insufficient
0x70 kUploadDownloadNotAccepted download cannot be accomplished due to fault

UDS_SRV_EVT_TransferData (0x36)

Arguments

typedef struct {
    const uint8_t *const data; /*! transfer data */
    const uint16_t len;        /*! transfer data length */
    /*! function for copying to the server send buffer. Returns `kPositiveResponse` on success and `kResponseTooLong` if the length of the data to be copied exceeds that of the server send buffer */
    uint8_t (*copyResponse)(
        UDSServer_t *srv, const void *src,
        uint16_t len);
} UDSTransferDataArgs_t;

Supported Responses

Value enum Meaning
0x00 kPositiveResponse Request accepted
0x31 kRequestOutOfRange data contents invalid, length incorrect
0x72 kGeneralProgrammingFailure Memory write failed
0x92 kVoltageTooHigh Can't write flash: voltage too high
0x93 kVoltageTooLow Can't write flash: voltage too low

UDS_SRV_EVT_RequestTransferExit (0x37)

Arguments

typedef struct {
    const uint8_t *const data; /*! request data */
    const uint16_t len;        /*! request data length */
    /*! function for copying to the server send buffer. Returns `kPositiveResponse` on success and `kResponseTooLong` if the length of the data to be copied exceeds that of the server send buffer */
    uint8_t (*copyResponse)(UDSServer_t *srv, const void *src,
                            uint16_t len);
} UDSRequestTransferExitArgs_t;

Supported Responses

Value enum Meaning
0x00 kPositiveResponse Request accepted
0x31 kRequestOutOfRange data contents invalid, length incorrect
0x72 kGeneralProgrammingFailure finalizing the data transfer failed

Examples

examples/README.md

Running Tests

make test

Contributing

contributions are welcome

Acknowledgements

  • isotp-c which this project embeds

Changelog

0.7.1

  • amalgamated sources into iso14229.c and iso14229.h to ease integration

0.7.0

  • test refactoring. theme: test invariance across different transports and processor architectures
  • breaking API changes:
    • overhauled transport layer implementation
    • simplified client and server init
    • UDS_ARCH_ renamed to UDS_SYS_

0.6.0

  • breaking API changes:
    • UDSClientErr_t merged into UDSErr_t
    • TP_SEND_INPROGRESS renamed to UDS_TP_SEND_IN_PROGRESS
    • refactored UDSTpHandle_t to encourage struct inheritance
    • UDS_TP_LINUX_SOCKET renamed to UDS_TP_ISOTP_SOCKET
  • added server fuzz test and qemu tests
  • cleaned up example tests, added isotp-c on socketcan to examples
  • added UDS_SRV_EVT_DoScheduledReset
  • improve client error handling

0.5.0

  • usability: refactored into a single .c/.h module
  • usability: default transport layer configs are now built-in
  • API cleanup: use UDS prefix on all exported functions
  • API cleanup: use a single callback function for all server events

0.4.0

  • refactor RDBIHandler to pass a function pointer that implements safe memmove rather than requiring the user to keep valid data around for an indefinite time or risking a buffer overflow.
  • Prefer fixed-width. Avoid using enum types as return types and in structures.
  • Transport layer is now pluggable and supports the linux kernel ISO-TP driver in addition to isotp-c. See examples.

0.3.0

  • added iso14229ClientRunSequenceBlocking(...)
  • added server and client examples
  • simplified test flow, deleted opaque macros and switch statements
  • flattened client and server main structs
  • simplified usage by moving isotp-c initialization parameters into server/client config structs
  • remove redundant buffers in server

0.2.0

  • removed all instances of __attribute__((packed))
  • refactored server download functional unit API to simplify testing
  • refactored tests
    • ordered by service
    • documented macros
  • removed middleware
  • simplified server routine control API
  • removed redundant function iso14229ServerEnableService
  • updated example

0.1.0

  • Add client
  • Add server SID 0x27 SecurityAccess
  • API changes

0.0.0

  • initial release

iso14229's People

Contributors

driftregion avatar markcorbinuk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

iso14229's Issues

isotp-c integration (updates)

Hi there!

A while ago you integrated my fork of the isotp-c library in this project.
I just wanted to inform you that several updates have been published since, and I thought it would be good to inform you.

The latest version is v1.1.1.

Implementations of function static int LinuxSockBind() and static int LinuxSockTpOpen() do not allow uint32_t rxid and txid

Thanks for the library. I appreciate your effort into this report @driftregion .

While trying to use your library to send/receive CAN frames with a 29 bit CAN ID, I realized that they would be casted to a unit16_t and this would then, off course, be a wrong address. I realized that it is because of how you implemented static int LinuxSockBind(const char *if_name, uint16_t rxid, uint16_t txid) and static int LinuxSockTpOpen(UDSTpHandle_t *hdl, const char *if_name, uint16_t phys_rxid, uint16_t phys_txid, uint16_t func_rxid, uint16_t func_txid). The rxid and txid just allow for 16 bit IDs even though the physical and functional send and receive IDs of UDSClientConfig_t are uint32_t.

My question is: Is there a special reason for it? CAN allows for the EFF (Extended Frame Format) flag to be set on the MSB of the 32 bit CAN ID to allow 29 bits for the CAN ID of the CAN frame. I then changed the function definition to static int LinuxSockBind(const char *if_name, uint32_t rxid, uint32_t txid) and static int LinuxSockTpOpen(UDSTpHandle_t *hdl, const char *if_name, uint32_t phys_rxid, uint32_t phys_txid, uint32_t func_rxid, uint32_t func_txid) and it worked as needed. I was wondering if that is something that could be changed in the repo for future users or if the rxid and txid are uint16_t for a specific reason that I'm not able to deduce.

Thanks in advance and great job implementing the ISO14229 standard! It's been of great help.

compiler warnings after upgrading to release v0.6.0

Hello @driftregion again,

after upgrading to the new release v0.6.0 and compiling with the flags -Wall and -Werror I get these two errors:

  1. [-Werror=int-to-pointer-cast]
 iso14229/iso14229.c:517:22: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
 517 |     *memoryAddress = (void *)tmp;

Regarding this error, does the tmp variable has to be of the type long long unsigned int? When I remove one long to make it long unsigned int, it compiles with no warnings (errors) - when using the -Werror flag warnings are made to errors. I would highly recommend to keep the standard of the library to compile with no warnings, no matter how "trivial".

  1. [-Werror=stringop-truncation]
armv7vet2hf-neon-poky-linux-gnueabi/usr/include/bits/string_fortified.h:106:10: error: ‘__builtin_strncpy’ specified bound 16 equals destination size [-Werror=stringop-truncation]
  106 |   return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));

First, I appreciate changing to the more secure variant strncpy(). I could fix this warning by changing the line 239 of iso14229.c from:

strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));

to

strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name) - 1);

Let me know what you think about these warnings and whether you think these changes are worth making.

How to use with PCAN

hello, @driftregion very big follower of your work sir

Iam having a bit hard time figuring out how to make this 14299.c, 14299. h to work with PCAN,
1)I have pcan installed in my system but I don't know how to make it work with code 14299. c since it does not have main function.

2)My main Aim is to check the data send from PCAN with our code for the respective diagnostic services (UDS) .
3) I would appreciate any help you could give me on how to do it.

Regards.

question on error behavior

the following might not be a real issue, but i would like to discuss the observation. We have a situation in which we act as a tester and the other nodes go into reboot/health check after an update. We then poll repeatedly to be aware when the nodes have rebooted. We needed to request idle in this situation, otherwise the lib stayed in UDS_ERR_BUSY even after the nodes had been back - no issue this is according to the examples.
However when we repeatedly send SendRDBI requests to get the status of the nodes while they are still not present, we get an oscillating pattern of errors: UDS_ERR_TIMEOUT, UDS_ERR_TPORT, UDS_ERR_TIMEOUT, UDS_ERR_TPORT etc.
we tried to understand how this happens and enabled the debug outputs:
client state: AwaitSendComplete (2) -> AwaitResponse (3)
read failed: -1 with errno: 70
timeout: 1
client state: AwaitResponse (3) -> Idle (0)
client state: Idle (0) -> Sending (1)
Condition met: client->send_size (3, 3), == ret (3)
Sending (1) -> AwaitSendComplete (2)
client state: AwaitSendComplete (2) -> AwaitResponse (3)
timeout: 1
client state: AwaitResponse (3) -> Idle (0)
awaiting idle failed with err = 1 and msg = 'UDS_ERR_TIMEOUT'
client state: Idle (0) -> Sending (1)
tport err: -1, nsend=3 bytes
Condition met: client->send_size (3, 3), == ret (3)
client state: Sending (1) -> AwaitSendComplete (2)
awaiting idle failed with err = 6 and msg = 'UDS_ERR_TPORT'
in the code imho this happens in:
case kRequestStateSending: {
UDSTpAddr_t ta_type = client->_options_copy & UDS_FUNCTIONAL ? UDS_A_TA_TYPE_FUNCTIONAL
: UDS_A_TA_TYPE_PHYSICAL;
UDSSDU_t info = {
.A_Mtype = UDS_A_MTYPE_DIAG,
.A_TA_Type = ta_type,
};
ssize_t ret = UDSTpSend(client->tp, client->send_buf, client->send_size, &info);
if (ret < 0) {
client->err = UDS_ERR_TPORT;

UDS_DBG_PRINT("tport err: %zd\n", ret);
} else if (0 == ret) {
UDS_DBG_PRINT("send in progress...\n");
; // 等待发送成功
} else if (client->send_size == ret) {
changeState(client, kRequestStateAwaitSendComplete);
} else {
client->err = UDS_ERR_BUFSIZ;
}
break;
and we are puzzled how ret < 0 can be true and shortly after client->send_size == ret??
Any idea from your experience?

Unpacking Security Access Level 1 Data

Hi again. I can not unpack request seed data by UnpackSecurityAccessResponse function.

Here is my debug output;

image

Could you give any example about security access level1 and level 2?

Addition:
image

I can request seed from the server, but, when I have to send encrypted data, I can not send concurrent data.

image

Is the problem timing? I think it is very very fast.

Solved : Sequence is not working properly

Hello again. I am using SequenceRunBlocking method, and I am trying the example codes.

Here are my sequences,

image

My problem is, I am sending DiagnosticSessionControl, awaitResponse is OK. But whenever I want to send CommunicationControl, It sends DiagnosticSessionControl again. I debugged the code row-by-row, it triggers CommunicationControl function, but it sends DiagnosticSessionControl.

Edit: Plase check CAN_MESSAGE_QUEUE_SIZE. Because in my code It was 1. Try to higher value.

Solved : Handling RX Data

Hello. Thanks for the library.

I have a question about handling responses. Im currently sending uds data and it looks OK. But, How can I handle the response? I mean,
How can I use the mockClientCANRxPoll function?

I modified mockClientSendCAN with HAL library for sending data. But I can not manage mockClientCANRxPoll.

Sorry for my bad English. Have a good day.

Edit1:

I tried something like this but It does not work

static enum Iso14229CANRxStatus mockClientCANRxPoll(uint32_t *arb_id, uint8_t *data, uint8_t *dlc) {
    
	HAL_CAN_GetRxMessage(&hcan1, CAN_RX_FIFO0, &rxHeader, TxData);


	*arb_id = rxHeader.ExtId;
	*dlc = rxHeader.DLC;
	memmove(data,TxData,*dlc);

    return kCANRxNone;
}

TransferData Question

Hi.
I have a question about TransferData with blocksize 128. I want to send data from client to server 128 byte packets. But I could not manage to use kISO14229_CLIENT_CALLBACK_PENDING and kISO14229_CLIENT_CALLBACK_DONE. How can I handle 128 byte packet is sent? I want to see positive TransferData response but I could not see.

I'm using SD CARD with FATFS. But TransferDataStream is using iostream. I could not use TransferDataStream with FATFS.

My first question is, Is there any other else TransferData function with blocksize 128?
Second question is, how can I use TransferDataStream with FATFS ?

Edit1: I am using iso14229ClientSequenceRunBlocking.

Is it possible to receive ALL responses to a functional request?

Hi, I'm trying to receive responses to a functional request (Diagnostic Session Control = Programming Session and RDBI) from different ECUs.

I know it's possible to send a functional request by setting the FUNCTIONAL bit of the options byte of the client before sending a request:

client->options |= FUNCTIONAL;

I can also receive one response, but, how can I receive ALL responses from the different ECUs on the same CAN bus?

Let's say there is three ECUs and I send a functional RDBI request to know the hardware versions of all of them: How could I receive he responses from all of them? Would I have to manually set the state of the client to kRequestStateAwaitSendComplete and wait for it (UDSClientPoll) to be IDLE again after receiving from the socket?

I would highly appreciate some help with this question, thanks in advance!

UDS client responding with a functional flow control frame to a physically addressed request

Hi @driftregion ,

when sending a physically addressed RDBI request to an ECU, that answers with a multi-frame RDBI response, the client sends two flow control frames, one that is physically addressed and the other functionally. Here is a log with candump:

(1688347721.008952) can0 18DAF140#103562FD13584355  /* response to RDBI request */
(1688347721.009126) can0 18DB00F1#301003  /* functionally addressed response even if the request was physically addressed */
(1688347721.009231) can0 18DA40F1#301003 /* physically addressed response */
(1688347721.012025) can0 18DAF140#215F544848000000

Sending two flow control frames makes the ECU answer twice, which is unnecessary and unwanted.

I'm not able to explain myself why this happens since in the function tp_recv the code for reading from the socket reads from the physical link first:

struct {
        int fd;
        UDSTpAddr_t ta_type;
    } arr[] = {{impl->phys_fd, kTpAddrTypePhysical}, {impl->func_fd, kTpAddrTypeFunctional}};
    for (size_t i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
        ret = read(arr[i].fd, buf, count);
        ...
        ...

After reading from the physical link, the socket should get the answer it needs and then not read another time from the functional link. Do you have an idea why this could be happening? If you need more info to the context or execute code, just let me know and thanks in advance!

working with flexcan in s32ds

Hi @driftregion iam facing an issue when working with the flexcan to uds currently this is how my initialization looks please guide me how to approach it :
1)Should i link the FLEXCAN to isotp-c to uds ?
2)i have made my custom flow control Should i directly link my flexcan to UDS ? [current approach]
i have been developing the code portable uds since last 6 months if possible can we connect and discuss ? please send me a mail to [email protected] so i can setup a teams meeting.

clean the memory of struct ifreq ifr and check the return value of ioctl for errors

Hello @driftregion ,

I tested creating some UDS clients with different interface names like "can2" or something like "can1234" to be surprised that the client could still be created and that it could send over the only available interface "can0". Then I realized that the variable struct ifreq ifr in the function static int LinuxSockBind() in the file iso14229.c is declared but its memory is not cleared before using it. After that, the return value of the call to ioctl() is not checked for errors like in the calls to socket(), setsockopt(), and bind() within the same function.

I think it did work because before I did these tests I had chosen the right interface name "can0" so the memory of the struct got the right index for interface but in another call with a wrong interface name, the call to ioctl was not successful but since the uncleared memory still uncleared the valid index for "can0" the client could still be bound to the right interface. I changed the code to:

    struct ifreq ifr;
    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name) - 1);
    if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
        printf("ioctl: %s %s\n", strerror(errno), if_name);
        return -1;
    }

and this prevents the problem and is a cleaner way of dealing with the struct and the call to ioctl. The warning message pattern was taken from the call to bind() after it.

I see that within the same function you use either perror or printf() to report errors, is there a reason for that? Wouldn't it be better to keep it consistent?

What do you think about this change?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.